问题主要在标题中。好像是 mfix
可以为任何一元计算定义,即使它可能会发散:
mfix :: (a -> m a) -> m a
mfix f = fix (join . liftM f)
这种结构有什么问题?另外,为什么
Monad
和 MonadFix
类型类分开(即,什么类型有 Monad
的实例,但没有 MonadFix
的实例)?
最佳答案
left shrinking (or tightening) law says那
mfix (\x -> a >>= \y -> f x y) = a >>= \y -> mfix (\x -> f x y)
这尤其意味着
mfix (\x -> a' >> f x) = a' >> mfix f
这意味着
mfix
内部的一元 Action 必须只计算一次。这是 MonadFix
的主要属性之一您的版本无法满足。考虑这个创建循环可变列表的示例(让我们忽略这样一个事实,即您可以在没有
mfix
的情况下这样做,这要归功于可变性):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
使用
mfix
的变体调用mrepeat
永远不会结束,因为你用 newIORef
调用内部部分无限期地。
关于haskell - 是否有 Monad 的实例但没有 MonadFix 的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25814489/