提问人:joel 提问时间:11/17/2023 最后编辑:K. A. Buhrjoel 更新时间:11/17/2023 访问量:127
为什么原位突变用“IO”表示?
Why is in-place mutation represented with `IO`?
问:
为什么在函数式语言中使用可变数据结构和其他可变性来表示?例如,我正在查看 Haskell 的 IORef
或 Idris 的 IOArray
。IO
我不认为这是一个历史或设计问题。我不太明白为什么适合突变——或者更确切地说,为什么突变在封装时变得纯粹。IO
IO
答:
4赞
leftaroundabout
11/17/2023
#1
您不需要用 .可以在 ST
中执行它们。但是你显然可以用 来表示它们,在那里可以实现任何肮脏的副作用。因此,如果你无论如何都在工作,最简单的方法是在那里进行突变,这样你就不需要担心将不同的单子焊接在一起。如果您还没有在 中工作,则应使用 但是。IO
IO
IO
IO
ST
评论
0赞
joel
11/17/2023
我熟悉假装用状态单子改变变量,但从文档来看,这主要是一个“突变”单子。它与编译为就地突变的状态单子有什么不同吗?ST
0赞
K. A. Buhr
11/17/2023
是的,这是不同的。monad 支持改变内存位置的编译器原语(参见 代码 )。据我所知,monad 永远不会被编译为在内存中改变状态的代码,至少在 GHC 中不会。最好将其视为“真正的”突变,使用 = + I/O 操作。ST
STRef
State
ST
IO
ST
0赞
Daniel Wagner
11/17/2023
@joel 尝试实现 using 而不是 (即 ),你会发现它们确实有很大不同。newSTRef
State
ST
newStateRef :: YourChoiceOfContextIDon'tMind s => State s (StateRef a)
0赞
Ben
11/17/2023
@joel 特别是,即使某些计算有时被优化为通过突变来执行,这几乎是偶然的。API 只处理值,事实上,早期的状态值在“更改”后仍然有引用是相当有效的,所以它显然不能总是作为突变实现。 有一个显式处理对可变存储的引用的 API;你指定突变,它们不是优化的偶然结果。State
State
ST
0赞
joel
11/18/2023
知道这一点非常有用。我一直以为人们在谈论状态时提到,给定吃。我实际上可以在我的工作中做到这一点ST
ST
ST
1赞
HTNW
11/18/2023
@joel 实施细节。你不能(或不应该)实际执行 IO。 应该是一个纯函数。ST
runST
下一个:号码分布
评论
IO
IO
data Op = Assign Int | Output
program = [Assign 1, Assign 2, Output, Assign 42, Output]
program
[2,42]
Assign 2
Output