gpt4 book ai didi

haskell - 为什么 ContT 不处理内部单子(monad)?

转载 作者:行者123 更新时间:2023-12-02 11:02:56 24 4
gpt4 key购买 nike

ContT 的绑定(bind)策略忽略内部 monad,实际上代码与 Cont 相同。

按照其他 Monad Transformers 的类比,我会这样实现它:

return x = ContT ($ (return x))
(>>=) x f = ContT (\k -> runContT x ((=<<) (\a -> runContT (f a) k)))

例如这个表达式:

do 
x1 <- ContT (\k -> k [1, 2])
x2 <- ContT (\k -> k [10, 20])
return ((+) x1 x2)

将导致[11, 21, 12, 22]

我的问题是这个设计决定背后的原因是什么?为什么是这样实现的,这使得它与其他 Monad Transformer 非常不同,注意仿函数实例是:

fmap f m = ContT $ \c -> runContT m (c . f)

而不是:

fmap f m = ContT $ runCont $ (fmap . fmap) f (Cont (runContT m))

这与其他 Monad Transformer 或多或少相同,但当前的实现似乎破坏了仿函数组合,我的意思是,由于 monad 不会自动组合,我们可能会讨论不同的绑定(bind)策略,但对于仿函数和应用程序来说,它应该总是一样的,而这里似乎完全不同。这是为了获得一些代表更多用例的代码而进行的黑客攻击吗?

偶数IdentityT确实如此,但我读到 Cont 的绑定(bind)策略实际上与 Identity 相同,那么 ContT 又如何呢? >身份T

最佳答案

(>>=) 不需要处理内部 monad (此外,不可能按照您建议的方式实现它,如 chi 所示),因为我们可以 提升一元值并获得所需的语义。

lift :: Monad m => m a -> ContT r m a
lift ma = ContT (ma >>=)

或者按照标准 library 中的规定:

instance MonadTrans (ContT r) where
lift m = ContT (m >>=)

现在我们有了

import Control.Monad.Trans.Cont
import Control.Monad.Trans.Class

test :: ContT r [] Int
test = do
x <- lift [1, 2]
y <- lift [10, 20]
return (x + y)

-- evalContT test == [11, 21, 12, 22]

换句话说,通过 ContT 的标准 monad 实例,我们已经可以任意操纵当前的延续,因此替代实现几乎无法给我们带来任何东西。

关于haskell - 为什么 ContT 不处理内部单子(monad)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28046173/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com