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