rwa*_*ace 3 monads haskell imperative-programming
从某种意义上说,Haskell 是一种纯粹的函数式语言,当然,惯用代码试图尽可能合理地函数式。同时,Haskell 确实支持对其他语言中熟悉的一些命令式模式的相当直接的翻译,例如http://learnyouahaskell.com/a-fistful-of-monads#do-notation
(我知道,从某种意义上说,do 表示法“确实”仍然有效;这里的要点是,它允许相当直接地翻译一些命令式设计模式。)
我感兴趣的一种模式是函数需要更新外部变量,即存在于与其他代码共享的外部作用域中的变量。这可以用 Python 简单地演示:
def three():
    n = 0
    def inc():
        nonlocal n
        n += 1
    inc()
    inc()
    inc()
    return n
是否有可能通过某种 do 表示法的变体或其他方式在 Haskell 中实现上述设计模式?如果是这样,怎么办?
为了明确这个问题的范围:
我不是问在 Haskell 中解决上述问题的最佳方法是什么。显然,答案是three = 3。这只是一个例子。
我不是在问上面的设计模式是好还是坏。显然,这是一个见仁见智的问题。
我并不是问在编写 Haskell 时应该如何努力避免使用命令式设计模式。显然,这也是一个意见问题。
我只是想问上面的设计模式是否可以在Haskell中实现,如果可以,如何实现。
chi*_*chi 13
在 Haskell 中,您所要做的就是在外部作用域中创建可变变量(实际上是对其的引用)并在内部作用域中使用它。
这里我使用ST smonad 来说明原理,但是您可以使用IO许多其他类型的引用来执行相同的操作。
import Control.Monad.ST
import Data.STRef
three :: ST s Int
three = do
   n <- newSTRef 0
   let inc = modifySTRef' n (+1)
   inc
   inc
   inc
   readSTRef n
main :: IO ()
main = print (runST three)   -- output: 3
请注意,在一般情况下,inc可能是一个do大块,可能在其范围内创建新引用(新局部变量),并具有自己的内部块。与 Python 中一样,作用域的嵌套没有限制。
| 归档时间: | 
 | 
| 查看次数: | 163 次 | 
| 最近记录: |