問題主要在標題中。這似乎是mfix
可以爲任何一元計算定義,即使它可能發散:是否有Monad的實例,但不是MonadFix的實例?
mfix :: (a -> m a) -> m a
mfix f = fix (join . liftM f)
什麼是錯的這種結構?此外,爲什麼Monad
和MonadFix
類型類是分開的(即哪些類型的實例是Monad
而不是MonadFix
)?
問題主要在標題中。這似乎是mfix
可以爲任何一元計算定義,即使它可能發散:是否有Monad的實例,但不是MonadFix的實例?
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
的一元行動必須精確評估一次。這是您的版本無法滿足的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
的內部部分。
您的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.
繼續monad沒有所需的定點操作符。 – augustss 2014-09-12 22:45:44
另請參閱[爲什麼MonadFix的實例不能用於連續monad?](http://stackoverflow.com/q/25827227/1333025)。 – 2014-09-14 15:48:45