在 Haskell 中通过引用传递?

Pass by Reference in Haskell?

来自 C# 背景,我会说 ref 关键字在某些情况下非常有用,在这些情况下,需要更改方法参数以直接影响设置参数的值类型的传递值至 null

此外,out 关键字在返回大量逻辑上不相关的值时可以派上用场。

我的问题是:在Haskell中是否可以通过引用将参数传递给函数?如果不是,直接替代方案是什么(如果有)?

My question is: is it possible to pass a parameter to a function by reference in Haskell? If not, what is the direct alternative (if any)?

不,Haskell 中的值是不可变的(好吧,do 表示法会产生一些可变性的错觉,但这一切都发生在函数内部,是一个完全不同的话题)。如果要更改值,则必须 return 更改后的值并让调用者处理它。例如,查看随机数生成函数 next return 的值 更新的 RNG。

Also, the out keyword can come in handy when returning a multitude of various logically unconnected values.

因此,您也不能 out。如果你想 return 几个完全断开连接的值(此时你可能应该考虑为什么断开连接的值是从单个函数 return 编辑的),return 一个元组。

这取决于上下文。没有任何上下文,不,你不能(至少不是你的意思)。有了上下文,如果你愿意,你很可能能够做到这一点。特别是,如果你在 IOST 中工作,你可以分别使用 IORefSTRef,以及可变数组、向量、哈希表、弱哈希表(我相信只有IO)等。一个函数可以采用其中的一个或多个并产生一个动作,该动作(在执行时)将修改这些引用的内容。

另一种上下文,StateT,给人一种纯粹实现的可变 "state" 值的错觉。您可以使用复合状态并将 lenses 传递给它,为某些目的模拟引用。

在 Haskell 和 ML 等语言中,"pass-by-value" 和 "pass-by-reference" 之间没有区别,因为在这些语言中无法为变量赋值。首先不可能让 "changes to a method parameter" 影响任何传递的变量。

不,这是不可能的,因为 Haskell 变量是不可变的,因此,Haskell 的创建者一定认为没有必要传递无法更改的引用。

考虑一个 Haskell 变量:

let x = 37

为了改变这个,我们需要制作一个临时变量,然后将第一个变量设置为临时变量(修改)。

let tripleX = x * 3
let x = tripleX

如果Haskell通过引用传递,我们可以这样做吗?
答案是

假设我们试过:

tripleVar :: Int -> IO()

tripleVar var = do

  let times_3 = var * 3
  let var = times_3


这段代码的问题是最后一行;虽然我们可以想象变量是通过引用传递的,但新变量不是。
换句话说,我们引入了一个新的 local 同名变量;

再看最后一行:

let var = times_3

Haskell不知道我们要"change"一个全局变量;因为我们不能重新分配它,所以我们在本地范围内创建一个具有相同名称的新变量,因此不会更改引用。 :-(


tripleVar :: Int -> IO()

tripleVar var = do
  let tripleVar = var
  let var = tripleVar * 3
  return()

main = do
  let x = 4
  tripleVar x
  print x -- 4 :(