gpt4 book ai didi

haskell - 卡在状态单子(monad)中

转载 作者:行者123 更新时间:2023-12-04 06:41:31 24 4
gpt4 key购买 nike

我想使用节点和唯一键的 IntMap 创建图形结构。这个话题已经很好地覆盖了herehere .我通过基本上将 state -> (val,state) 的函数包装在一个新类型中来理解 state monad 的工作原理,这样我们就可以为它创建一个 monad 实例。我已经阅读了很多关于这个主题的内容。我似乎仍然无法理解如何在整个程序执行过程中获得唯一(或只是增量)值。获得一系列连续的 ID 很容易,但是一旦我“runState”退出 monad,我似乎又回到了开始跟踪当前 ID 的地方。我觉得我被困在单子(monad)里了。我考虑的另一个选择是将整个 IntMap 和当前的“下一个”ID 保留为状态,但这似乎非常“必要”和极端。 This问题非常相似,但没有得到很多答案(或者我只是遗漏了一些明显的东西)。在整个程序执行过程中,利用 state monad 获取唯一 ID 的惯用方法是什么?谢谢。

最佳答案

假设我们要去IO -化 State单子(monad)。那会是什么样子?我们的纯State monad 只是一个新类型:

s -> (a, s)

好吧, IO在返回最终值之前,版本可能会产生一些副作用,如下所示:
s -> IO (a, s)

这种模式很常见,它有一个名字,特别是 StateT :
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }

该名称有 T最后因为它是一个 monad T变形金刚。我们调用 m “基本单子(monad)”和 StateT s m “转化”的单子(monad)。
StateT s m只是一个 Monad如果 mMonad :
instance (Monad m) => Monad (StateT s m) where {- great exercise -}

然而,除此之外,所有 monad 转换器都实现了 MonadTrans类,定义如下:
class MonadTrans t where
lift :: (Monad m) => m a -> t m a

instance MonadTrans (StateT s) where {- great exercise -}

如果 tStateT s ,然后 lift的类型专门用于:
lift :: m a -> StateT s m a

换句话说,它让我们“提升”基本单子(monad)中的一个 Action ,使其成为转换后的单子(monad)中的一个 Action 。

因此,对于您的具体问题,您需要 StateT (IntMap k v) IO monad,扩展 IO附加 State .然后你可以在这个 monad 中编写你的整个程序:
main = flip runStateT (initialState :: IntMap k v) $ do
m <- get -- retrieve the map
lift $ print m -- lift an IO action
(k, v) <- lift readLn
put (insert k v m)

请注意,我仍然使用 getput .那是因为 transformers包实现了我描述的所有概念,它概括了 get 的签名和 put成为:
get :: (Monad m) => StateT s m s
put :: (Monad m) => s -> StateT s m ()

这意味着它们会自动在 StateT 内工作。 . transformers然后只定义 State作为:
type State s = StateT s Identity

这意味着您可以使用 getput两个 StateStateT .

要了解有关 monad 转换器的更多信息,我强烈推荐 Monad Transformers - Step by Step .

关于haskell - 卡在状态单子(monad)中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14516835/

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