Haskell 中 `do` 之外的 ST Monad 用法?
ST Monad usage outside of `do` in Haskell?
我在 do
符号的上下文中看到了很多 ST monad 的例子;然而,由于这不适合我的目的,我尝试在 do
线程之外使用 ST monad 例如 newSTRef
和 modifySTRef
。
类型由VSCode的HLS自动添加。
ref :: ST s (STRef s Integer)
ref = newSTRef (1)
x :: ST s ()
x = modifySTRef ref 2
错误:最后一行ref
Couldn't match expected type ‘STRef s a0’
with actual type ‘ST s0 (STRef s0 Integer)’
好吧,我当然可以看到类型不匹配的错误,但我不知道如何修复它。
ST Monad 在 do
之外的正确用法是什么?
编辑:
没有do
我的目的是
就像上面提到的那样,do
只是一种语法糖,通常我想避免它以便以更直接的功能方式编写代码。
获取可变对象的目的是为了开发FRP,单do
线程中ref
的顺序定义和更新没有用处。
这里的问题是 modifySTRef
需要一个 STRef s a
,而不是 ST s (STRef s a)
。 ST
旨在利用 monad 属性来保护可变操作不被滥用,因此所有修改只能在 ST
上下文中发生。因此,您需要使用上下文的力量来提取纯 STRef
引用。
通常你会do
这样:
x :: ST s ()
x = do
refv <- ref
modifySTRef refv 2
但是既然你想避免这种糖,你可以做正确的脱糖:
x :: ST s ()
x = refv >>= \refv -> modifySTRef refv 2
您可以阅读有关 do
表示法及其解析方式的更多信息 here
评论中的评论:请注意,您的代码 没有 这样的全局变量。 newSTRef
每次在 ST context 中调用时分配一块新的 RAM 。因此,此示例中的 x
实际上什么也没做(除了浪费一些内存和 GC 时间)。
如果您打算保留参考文献,则必须将其“拿在手中”,例如放在 ReaderT
包装纸中。
我在 do
符号的上下文中看到了很多 ST monad 的例子;然而,由于这不适合我的目的,我尝试在 do
线程之外使用 ST monad 例如 newSTRef
和 modifySTRef
。
类型由VSCode的HLS自动添加。
ref :: ST s (STRef s Integer)
ref = newSTRef (1)
x :: ST s ()
x = modifySTRef ref 2
错误:最后一行ref
Couldn't match expected type ‘STRef s a0’
with actual type ‘ST s0 (STRef s0 Integer)’
好吧,我当然可以看到类型不匹配的错误,但我不知道如何修复它。
ST Monad 在 do
之外的正确用法是什么?
编辑:
没有do
我的目的是
就像上面提到的那样,
do
只是一种语法糖,通常我想避免它以便以更直接的功能方式编写代码。获取可变对象的目的是为了开发FRP,单
do
线程中ref
的顺序定义和更新没有用处。
这里的问题是 modifySTRef
需要一个 STRef s a
,而不是 ST s (STRef s a)
。 ST
旨在利用 monad 属性来保护可变操作不被滥用,因此所有修改只能在 ST
上下文中发生。因此,您需要使用上下文的力量来提取纯 STRef
引用。
通常你会do
这样:
x :: ST s ()
x = do
refv <- ref
modifySTRef refv 2
但是既然你想避免这种糖,你可以做正确的脱糖:
x :: ST s ()
x = refv >>= \refv -> modifySTRef refv 2
您可以阅读有关 do
表示法及其解析方式的更多信息 here
评论中的评论:请注意,您的代码 没有 这样的全局变量。 newSTRef
每次在 ST context 中调用时分配一块新的 RAM 。因此,此示例中的 x
实际上什么也没做(除了浪费一些内存和 GC 时间)。
如果您打算保留参考文献,则必须将其“拿在手中”,例如放在 ReaderT
包装纸中。