gpt4 book ai didi

haskell - 具有多个状态值的状态单子(monad)

转载 作者:行者123 更新时间:2023-12-04 01:56:53 25 4
gpt4 key购买 nike

考虑以下:

do
x1 <- new 2
set x1 3
x2 <- get x1
y1 <- new 10
set y1 20
y2 <- get y1
return (x2 + y2)

我希望这会导致 23 .有没有办法在纯 Haskell 中实现这样的东西,如果是这样,怎么做?我了解 STRef做这样的事情,但我只想在普通的Haskell中做(目前不担心效率)。我想我必须创建一个数据类型并使其成为 Monad 的实例,但我不确定细节,所以一个工作示例会很有帮助。

最佳答案

这允许多个值,但它更复杂 :) Daniel 的建议很好地简化了 Dynamic .

import Data.Dynamic
import Data.Maybe
import Control.Monad.State
import Data.Map as M

newtype Ref a = Ref {ref :: Int}

type MutState = State (Int, Map Int Dynamic)

val :: Typeable a => Ref a -> MutState a
val r = snd `fmap` get >>=
return . fromJust . (>>= fromDynamic) . M.lookup (ref r)

new :: Typeable a => a -> MutState (Ref a)
new a = do
(curr, binds) <- get
put (curr + 1, M.insert (curr + 1) (toDyn a) binds)
return . Ref $ curr + 1

set :: Typeable a => Ref a -> a -> MutState ()
set (Ref i) a = do
(c, m) <- get
put (c, M.insert i (toDyn a) m)

runMut :: MutState a -> a
runMut = flip evalState (0, M.fromList [])

然后使用它
default (Int) -- too lazy for signatures :)
test :: Int
test = runMut $ do
x1 <- new 2
set x1 3
x2 <- val x1
y1 <- new 10
set y1 20
y2 <- val y1
return (x2 + y2)
Ref s 基本上是 Int s 附加了一些类型信息和 val将查找相应的 Dynamic并尝试将其强制转换为正确的类型。

如果这是真实的代码,你应该隐藏 Ref 的实现。和 MutState .为方便起见,我有 fromJust ed 返回 val如果你想要一个安全的实现,我想你可以分层 StateMaybe monads 来处理未绑定(bind)的变量。

如果您担心可键入的约束,如上所示,它们是微不足道的。

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

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