【问题标题】:Is there an instance of Monad but not of MonadFix?是否有 Monad 的实例但没有 MonadFix 的实例?
【发布时间】:2014-11-06 23:58:22
【问题描述】:

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

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

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

【问题讨论】:

标签: haskell monads monadfix


【解决方案1】:

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 调用内部部分。

【讨论】:

    【解决方案2】:

    不保证您对mfix 的定义等同于标准定义。事实上,至少在 list monad 中它更严格:

    > 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.
    

    【讨论】:

      猜你喜欢
      • 2011-07-18
      • 2016-11-05
      • 2012-06-19
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多