更新Haskell中的外部变量 [英] Updating an outer variable in Haskell

查看:0
本文介绍了更新Haskell中的外部变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从某种意义上说,Haskell是一种纯粹的函数式语言,当然,习惯用法代码试图尽可能地具有函数性。同时,Haskell确实支持对其他语言中熟悉的一些命令式模式进行相当直接的翻译,例如http://learnyouahaskell.com/a-fistful-of-monads#do-notation

(我知道在某种意义上,do-notation仍然"真正"起作用;这里的要点是,它允许相当直接地转换一些命令性设计模式。)

我感兴趣的一种模式是函数需要更新外部变量,即与其他代码共享的外部作用域中的变量。这可以简单地在Python中演示:

def three():
    n = 0

    def inc():
        nonlocal n
        n += 1

    inc()
    inc()
    inc()
    return n
是否有可能在Haskell中实现上述设计模式,也许可以使用DO表示法的某个变体,或者使用其他方法?如果是,如何?

要明确这个问题的范围:

我不是在问在Haskell中解决上述问题的最佳方法是什么。显然,答案将是three = 3。这只是一个例子。

我不是在问上面的设计模式是好是坏。显然,这将是一个见仁见智的问题。

我不是问在编写Haskell时,应该如何努力避免使用命令式设计模式。显然,这也是一个见仁见智的问题。

我只是想知道上面的设计模式是否可以在Haskell中实现,如果可以,如何实现。

推荐答案

在Haskell中,您所要做的就是在外部作用域中创建可变变量(实际上是对该变量的引用),并在内部作用域中使用它。

这里我使用ST s单体来说明原理,但您也可以使用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中一样,作用域的嵌套没有限制。

这篇关于更新Haskell中的外部变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆