在Haskell中通过引用?

时间:2016-02-25 00:35:55

标签: haskell pass-by-reference

来自C#背景,我想说ref关键字在某些情况下非常有用,在这些情况下,希望对方法参数进行更改,以直接影响用于将参数设置为{的值类型的传递值{1}}。

此外,当返回大量各种逻辑上未连接的值时,null关键字可以派上用场。

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

4 个答案:

答案 0 :(得分:7)

在Haskell和ML等语言中,“pass-by-value”和“pass-by-reference”之间没有区别,因为无法分配这些语言中的变量。在影响任何传递的变量时,首先不可能对方法参数进行“更改”。

答案 1 :(得分:5)

  

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

不,Haskell中的值是不可变的(好吧,do符号可以创建一些可变性的错觉,但它都发生在函数内部并且是完全不同的主题)。如果要更改值,则必须返回更改的值并让调用者处理它。例如,请参阅随机数生成函数next,它返回值更新的RNG。

  

此外,当返回大量各种逻辑上未连接的值时,out关键字可以派上用场。

因此,您也不能拥有out。如果你想返回几个完全断开连接的值(此时你应该想到为什么从单个函数返回断开的值),返回一个元组。

答案 2 :(得分:5)

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

另一种上下文StateT给出了纯粹实现的可变“状态”值的错觉。您可以使用复合状态并将镜头传递到其中,为某些目的模拟参考。

答案 3 :(得分:0)

不,这是不可能的,因为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不知道我们要“更改”全局变量。由于我们无法重新分配它,因此我们将在本地范围内创建一个具有相同名称的新变量,从而不会更改引用。 :-(


tripleVar :: Int -> IO()

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

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