The left shrinking (or tightening) law says that
mfix (\x -> a >>= \y -> f x y) = a >>= \y -> mfix (\x -> f x y)
In particular this means that
mfix (\x -> a' >> f x) = a' >> mfix f
which means that the monadic action inside mfix
must be evaluated exactly once. This is one of the main properties of MonadFix
which your version fails to satisfy.
Consider this example that creates a cyclic mutable list (let's disregard the fact that you could do that without mfix
thanks to mutability):
import Control.Monad
import Control.Monad.Fix
import Data.IORef
data MList a = Nil | Cons a (IORef (MList a))
mrepeat :: a -> IO (MList a)
mrepeat x = mfix (liftM (Cons x) . newIORef)
main = do
(Cons x _) <- mrepeat 1
print x
With your variant of mfix
the call to mrepeat
never finishes, as you're calling the inner part with newIORef
indefinitely.