为什么在`MaybeT`中``mfix`不是完全的

时间:2018-04-02 14:59:59

标签: haskell monads monadfix

如果函数评估为MonadFix,则MaybeT的{​​{1}} transformers implementation会失败。为什么Nothing不会在Nothing上传播?

mfix

我必须有一个很好的理由,因为mfix' :: MonadFix m => (a -> MaybeT m a) -> MaybeT m a mfix' f = MaybeT $ mfix $ \case Nothing -> return Nothing Just x -> runMaybeT $ f x 根本没有实现ListTMonadFix如上所述实现了in the same way

2 个答案:

答案 0 :(得分:2)

我认为问题只是error消息具有误导性。我们只关注MonadFix Maybemfix的论证可以是四件事之一。

  1. 输入可以是严格的:f _|_ = _|_或“f需要评估其输入,以确定它是否会返回NothingJust”< / p>

    \x -> if x then Nothing else Just True
    \x -> x `seq` Nothing
    \x -> x `seq` Just x
    
  2. 可以是const Nothing

  3. 可能Just . f f不严格。

    Just . (1:)
    
  4. 可能Just . f f严格。

    Just
    
  5. 如果函数是严格的,那么整个事情就会在无限循环中爆炸(就像fix一样),并且看不到错误,因为我们不知道我们是否会有{{{ 1}}或Nothing。如果它是Just,则该函数实际上从未尝试评估const Nothing,并且没有任何反应。如果它是errorJust . f不严格,那么它只是f(根据法律:Just $ fix f)。而且,如果mfix $ return . f = return $ fix f是严格的,我们会f(同样,根据法律)。请注意,我们从未看到Just _|_已触发。

    类似的推理适用于error。我想这一次最好只举一个例子:

    MonadFix (MaybeT m)

    上面列出的四种情况中的每一种都在该列表中。结果的第一个元素是无限循环。第二个是runMaybeT $ mfix $ \x -> MaybeT $ (x `seq` Nothing) : Nothing : (Just (1:x)) : (Just x) : (x `seq` []) 。第三个是Nothing,第四个是repeat 1无限循环。试图访问超出该元素的“元素”会触发另一个无限循环,这次由Just的{​​{1}}而不是[]引起。同样,我不相信触发MonadFix是可能的,因为在确定结果为MaybeT之后,函数必须强制参数。

答案 1 :(得分:2)

bomb的定义在引用的库定义中确实非常混乱,尽管函数本身已正确实现。通过单调性,满足f的任何函数f undefined = Nothing必须等于const Nothing。因此,定点计算将简单地产生包含在变换器堆栈中的Nothing的正确答案。

有关详细信息,请参阅this work的第4.9节,尽管原始定义为了清晰起见省略了构造函数,但使用了名称ErrT而不是MaybeT。 (那时候MTL并不存在!)其定义如下:

mfixErrM :: (α → ErrT m α) → ErrT m α
mfixErrM f = mfixM (f · unErr)
     where unErr (Ok a) = a

附录B.7中还有一个证明,表明只要基础ErrT m是有效的值递归运算符,这是mfixM的有效值递归运算符m