gpt4 book ai didi

haskell - 为什么电梯的返回值不被限制为单子(monad)?

转载 作者:行者123 更新时间:2023-12-04 13:32:44 25 4
gpt4 key购买 nike

为什么不是 MonadTrans定义为

class MonadTrans t where
lift :: (Monad m, Monad (t m)) => m a -> t m a
-- ^^^^^^^^^^^

而不是当前

class MonadTrans t where
lift :: Monad m => m a -> t m a


这是 Haskell 98(与 Why aren't monad transformers constrained to yield monads? 中的建议不同)并确保结果始终是单子(monad)。允许单子(monad)转换器产生不是单子(monad)的东西有什么原因吗?

最佳答案

bheklilr 的回答让我想到了一个例子,在这个例子中,monad 转换器产生了一些不是 monad 的东西。一个不是 monad 的著名例子是 ZipList 。我们可以制作一个变体,在每个级别运行一个单子(monad) Action :

import Control.Applicative
import Control.Arrow ((***))
import Control.Monad
import Control.Monad.Trans

-- | A list where each step is produced by a monadic action.
data ListT m a = Nil | Cons (m (a, ListT m a))

这实际上是一个 monad 流。并且可以很容易地做成一个 Functor和一个 Applicative
instance Monad m => Functor (ListT m) where
fmap f Nil = Nil
fmap f (Cons k) = Cons $ (f *** fmap f) `liftM` k
instance Monad m => Applicative (ListT m) where
pure x = Cons $ return (x, pure x)
Cons mf <*> Cons mx = Cons $ do
(f, fs) <- mf
(x, xs) <- mx
return (f x, fs <*> xs)
_ <*> _ = Nil

但显然不是单子(monad)。所以我们有一个 MonadTrans 实例,它将一个单子(monad)转换成一个只有 Applicative 的东西。
instance MonadTrans ListT where
lift mx = Cons $ (\x -> (x, lift mx)) `liftM` mx

(这整件事让我意识到,conduit-extra 中的实验性 ZipSink 也是一个很好的例子。)

然而,这又提出了另一个问题:如果我们想要这样的变形金刚,它们应该遵守什么法律? MonadTrans 的定律定义为

lift . return = return
lift (m >>= f) = lift m >>= (lift . f)


所以在我们的例子中,我们可能希望像
lift (f `liftM` x)  = fmap f (lift x)

lift . return = pure
lift (m `ap` f) = lift m <*> lift f

关于haskell - 为什么电梯的返回值不被限制为单子(monad)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18494010/

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