为被runST执行,ST的状态是否需保持不变?
关于Haskell中runST与参数性的探讨
先看这段ST和runST的定义(存在不少错误,但runST的核心结构如下):
type ST s a = ST (s -> (s, a)) runST :: (forall s. ST s a) -> a runST (ST f) = case (f realWorld) of (_, a) -> a
要将runST应用于类型为ST s a(等价于s -> (s, a))的值,类型s必须是完全参数化的。
无法被runST应用的函数示例
部分依赖具体类型的函数无法通过runST执行,比如:
\s -> (s + s, "hello world") -- 无法运行,依赖Num类型类 fun [] = ([], 0) fun (x : xs) = (xs, length (x : xs)) -- 无法运行,依赖[]类型
可被runST执行的函数形式
符合要求的函数结构应该如下:
\s -> (s, fun s) fun = maybe some native code, not haskell.
关键在于,s -> (s, a)中返回的s必须和输入的s完全一致,类似恒等操作,这就是参数性(parametricity)。
关于RealWorld与State#的猜想
我了解到,如果s包含RealWorld,哪怕看似是恒等操作,也能完成有意义的计算(尽管这不属于纯Haskell范畴)。
为验证这个猜想,我设计了一个实验:
//given newMutVar# :: v -> State# s -> (# State# s, MutVar# s v #) //then (this is pseudo code) let (# s#, var# #) = newMutVar# "hello world" (State# 0) in s# == State# 0
我想确认结果是否为True——若是,就说明newMutVar#对State#的作用类似恒等操作。
但我没法完成这个实验,原因有两点:
- 我不知道如何生成
State# s类型的值,仅了解对应RealWorld的值生成方式,但这没有意义,因为RealWorld内部只有一个值,无论映射逻辑如何它都不会改变。 - 即便能生成
State# 0,也无法和s#比较,因为State# s并未实现Eq类型类。
内容的提问来源于stack exchange,提问作者kwonryul
相关产品推荐
相关产品推荐

