Haskell 是否存在Monad而非MonadFix的实例?

Haskell 是否存在Monad而非MonadFix的实例?,haskell,monads,monadfix,Haskell,Monads,Monadfix,问题主要在标题中。似乎可以为任何一元计算定义mfix,即使它可能会偏离: mfix :: (a -> m a) -> m a mfix f = fix (join . liftM f) 这种结构有什么问题?另外,为什么Monad和MonadFix类型类是分开的(即什么类型有Monad的实例,但没有MonadFix)?您对mfix的定义不能保证等同于标准的定义。事实上,至少在单子列表中,它更为严格: > take 1 $ mfix (\x -> [1,x]) [1] &g

问题主要在标题中。似乎可以为任何一元计算定义
mfix
,即使它可能会偏离:

mfix :: (a -> m a) -> m a
mfix f = fix (join . liftM f)

这种结构有什么问题?另外,为什么
Monad
MonadFix
类型类是分开的(即什么类型有
Monad
的实例,但没有
MonadFix
)?

您对
mfix
的定义不能保证等同于标准的定义。事实上,至少在单子列表中,它更为严格:

> take 1 $ mfix (\x -> [1,x])
[1]
> let mfix2 :: Monad m => (a -> m a) -> m a; mfix2 f = fix (join . liftM f)
> take 1 $ mfix2 (\x -> [1,x])
Interrupted.
那个

这尤其意味着

mfix (\x -> a' >> f x)  =  a' >> mfix f
这意味着
mfix
中的一元操作必须精确计算一次。这是您的版本无法满足的
MonadFix
的主要属性之一

考虑这个创建循环可变列表的示例(让我们忽略一个事实,即由于可变性,您可以在不使用
mfix
的情况下执行此操作):

import-Control.Monad
导入控制.Monad.Fix
导入数据.IORef
数据MList a=Nil | Cons a(IORef(MList a))
mrepeat::a->IO(MList a)
mrepeat x=mfix(liftM(Cons x).newIORef)
main=do

(Cons x_)延续单元没有所需的不动点运算符。另请参见。
mfix (\x -> a' >> f x)  =  a' >> mfix f
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