You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中MutVar#是否为不纯操作?State/ST/STRef相关困惑

解析Haskell中MutVar#的纯性疑问

核心结论

MutVar# 及其相关API是纯的,你产生误解的根源是忽略了 State# 作为操作输入的关键作用。

关键概念澄清

  • State# RealWorld 不是普通的"值",它是程序全局状态的唯一令牌。每次涉及可变操作(如创建、读写MutVar#)时,都会生成一个新的 State#,代表操作完成后的世界状态。
  • Haskell的纯性要求是相同输入必须得到相同输出,而MutVar#的操作(如readMutVar#)的输入是**MutVar# s a + State# s**的组合,而非单独的MutVar#。

针对你的代码分析

你的代码中,readMutVar#的调用并非使用"相同输入":

fun :: State# RealWorld -> (Int, Int, Int)
fun s# = let 
    (# a#, var# #) :: (# State# RealWorld, MutVar# RealWorld Int #) = newMutVar# 0 s#
    -- 传入原始状态s#,此时var#在s#对应的状态下值为0
    (# b#, o1 #) :: (# State# RealWorld, Int #) = readMutVar# var# s#
    -- 基于new后的状态a#执行写入,得到新状态c#
    c# = writeMutVar# var# 10 a#
    -- 传入写入后的状态c#读取,得到10
    (# d#, o2 #) :: (# State# RealWorld, Int #) = readMutVar# var# c#
    -- 基于c#执行第二次写入,得到新状态e#
    e# = writeMutVar# var# 20 c#
    -- 传入e#读取,得到20
    (# f#, o3 #) :: (# State# RealWorld, Int #) = readMutVar# var# e# 
in
    (o1, o2, o3)
  • 每次readMutVar#的State#输入都是不同的(s#、c#、e#),因此输入组合(var# + State#)并不相同,输出不同完全符合纯函数的要求。
  • 当你多次传入realWorld#调用fun时,每次都会得到相同的(0,10,20)结果,这证明fun是纯函数——相同输入始终得到相同输出。

ST/State与纯性的关联

  • State Monad的s -> (s,a)结构是纯函数式的状态传递,通过显式传递不可变的状态值来模拟状态变化。
  • ST Monad则是通过State#和类型系统(带 phantom type s)来封装可变操作,确保可变变量无法逃逸出ST作用域,从而在保证局部可变性的同时,维持整个程序的纯性。MutVar#是STRef的底层实现,它的操作必须结合State#来使用,而State#的传递确保了操作顺序和状态一致性,全程没有违反纯性。

内容的提问来源于stack exchange,提问作者kwonryul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:07:37