用于改变其周围环境的函数的Haskell表达式?

Haskell 是一种纯函数式语言,它为命令式表达式的等价物提供语法糖。例如,这个 Python 代码:

def f():
    n = 0
    for i in range(10):
        n += 1
    return n

可以使用 monad 逐行翻译成同构的 Haskell 代码。

函数改变其周围环境的代码也是如此吗?例如:

def f():
    n = 0
    def g():
        nonlocal n
        n += 1
    for i in range(10):
        g()
    return n

有没有办法将上面的一行一行翻译成同构的 Haskell?

我已经完全准备好接受答案是否定的,需要重新设计代码才能以不同的方式做同样的事情。但我认为值得询问是否有同构翻译。

回答

您可以使用 aState来封装State.

在这种情况下,您g可以看起来像:

import Control.Monad.State.Lazy(State, modify)

g :: State Int ()
g = modify (1+)

thenf也是一个State首先将状态设置为0然后运行g十次的:

import Control.Monad(replicateM_)
import Control.Monad.State.Lazy(State, get, put)

f :: State Int Int
f = do
    put 0
    replicateM_ 10 g
    get

然后你可以在我们提供初始状态的地方运行fevalState :: State s a -> s -> a它将返回项目的结果State s a,所以这里get返回的是什么:

Prelude Control.Monad.State.Lazy> evalState f 0
10

  • I was preparing to use `forM_ [1..10]` because it's slightly more similar to the Python in that `[1..10]` matches `range(10)`, but `replicateM_ 10` is undoubtedly superior.
  • Hm, with `State` the notion of scope doesn't seem to translate as easily. With only a single variable `n` it's simple, but what if you incremented two different variables in that loop? How to represent the closure of `g` over `n`? I think this needs a `STRef` or something similar.
  • @Bergi Indeed. I can see the following options to model multiple variables: 1) `State (Int, String, .....)` and suitable updates for the right component, 2) the same, but with records, 3) `STRef`s, 4) `IORef`s. One might need `ContT` on top if non-local returns are needed (`break`, `raise Exception`, `longjmp`). For complex algorithms, `STRef`s seem good enough, unless IO is needed.

以上是用于改变其周围环境的函数的Haskell表达式?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>