gpt4 book ai didi

haskell - 在 Haskell 中为状态创建只读函数

转载 作者:行者123 更新时间:2023-12-03 15:12:47 28 4
gpt4 key购买 nike

我经常遇到使用 State 非常方便的情况。 monad,因为有很多相关的函数需要以半命令式的方式对同一条数据进行操作。

有些函数需要读取 State monad 中的数据,但永远不需要更改它。使用 State monad 在这些函数中像往常一样工作得很好,但我不禁觉得我已经放弃了 Haskell 固有的安全性并复制了一种任何函数都可以改变任何东西的语言。

我可以做一些类型级别的事情来确保这些函数只能从 State 中读取吗? ,并且从不写信给它?

现在的情况:

iWriteData :: Int -> State MyState ()
iWriteData n = do
state <- get
put (doSomething n state)

-- Ideally this type would show that the state can't change.
iReadData :: State MyState Int
iReadData = do
state <- get
return (getPieceOf state)

bigFunction :: State MyState ()
bigFunction = do
iWriteData 5
iWriteData 10
num <- iReadData -- How do we know that the state wasn't modified?
iWRiteData num

理想情况下 iReadData可能有类型 Reader MyState Int , 但是它不能很好地与 State 配合使用.有 iReadData成为一个常规函数似乎是最好的选择,但是我必须通过每次使用它时明确地提取和传递状态的体操。我有哪些选择?

最佳答案

注入(inject) Reader 并不难单子(monad)进入 State :

read :: Reader s a -> State s a
read a = gets (runReader a)

那么你可以说
iReadData :: Reader MyState Int
iReadData = do
state <- ask
return (getPieceOf state)

并将其称为
x <- read $ iReadData

这将允许您建立 Reader s 到更大的只读子程序中并将它们注入(inject) State只有在你需要将它们与更改器(mutator)结合的地方。

将其扩展到 ReaderT 并不难和 StateT在 monad 转换器堆栈的顶部(实际上,上面的定义完全适用于这种情况,只需更改类型)。将其扩展到 ReaderTStateT在堆栈的中间更难。你基本上需要一个功能
lift1 :: (forall a. m0 a -> m1 a) -> t m0 a -> t m1 a

对于每个单子(monad)变压器 tReaderT 上方的堆栈中/ StateT ,它不是标准库的一部分。

关于haskell - 在 Haskell 中为状态创建只读函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28587132/

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