The question is mostly in the title. It seems like mfix can be defined for any monadic computation, even though it might diverge:
mfix :: (a -> m a) -> m a
mfix f = fix (join . liftM f)
What is wrong with this construction? Also, why are the Monad and MonadFix typeclasses separate (i.e. what type has an instance of Monad but not of MonadFix)?
The left shrinking (or tightening) law says that
In particular this means that
which means that the monadic action inside
mfixmust be evaluated exactly once. This is one of the main properties ofMonadFixwhich 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
mfixthanks to mutability):With your variant of
mfixthe call tomrepeatnever finishes, as you're calling the inner part withnewIORefindefinitely.