gpt4 book ai didi

haskell - monad 变压器何时需要提升?

转载 作者:行者123 更新时间:2023-12-04 09:58:01 24 4
gpt4 key购买 nike

我正在学习单子(monad)更改器(mutator),我对何时需要使用电梯感到困惑。
假设我有以下代码(它没有做任何有趣的事情,只是我可以用来演示的最简单的代码)。

foo :: Int -> State Int Int
foo x = do
(`runContT` pure) $ do
callCC $ \exit -> do
when (odd x) $ do
-- lift unnecessary
a <- get
put $ 2*a
when (x >= 5) $ do
-- lift unnecessary, but there is exit
a <- get
exit a
when (x < 0) $ do
-- lift necessary
a <- lift $ foo (x + 10)
lift $ put a

lift get

所以有一个 monad 堆栈,其中 main do block 的类型为 ContT Int (StateT Int Identity) Int .

现在,在第三个 when do block with recursion 编译程序需要一个提升。在第二个街区,不需要电梯,但我不知何故认为这是因为 exit 的存在。以某种方式强制将线上方的线提升到 ContT .但在第一个街区,不需要电梯。 (但如果明确添加,也没有问题。)这真的让我很困惑。我觉得所有的 when do block 是等效的,无论在任何地方都应该需要电梯。但这显然不是真的。需要/不需要电梯的关键区别在哪里?

最佳答案

由于您使用的 monad 转换器库有点聪明,因此这里出现了困惑。具体来说,get 的类型和 put没有明确提及 StateStateT .相反,它们是沿线的

get :: MonadState s m => m s
put :: MonadState s m => s -> m ()

因此,只要我们在带有 MonadState 的上下文中使用它实现 monad 不需要显式 lift s。在您使用 get 的所有实例中都是这种情况。/ put自从
instance MonadState s (StateT s m)
instance MonadState s m => ContT k m

两者都持有。换句话说,类型类解析将自动为您处理适当的提升。这反过来意味着您可以省略 liftget/ put在你的程序结束时。

递归调用不会发生这种情况,因为它的类型是明确的 State Int Int .如果将其概括为 MonadState Int m => m Int你甚至可以省略这最后的电梯。

关于haskell - monad 变压器何时需要提升?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45236226/

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