3

Coming from a C# background, I would say that the ref keyword is very useful in certain situations where changes to a method parameter are desired to directly influence the passed value for value types of for setting a parameter to null.

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

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)?

MathuSum Mut
  • 2,765
  • 3
  • 27
  • 59
  • 1
    yes, you can pass by reference and mutate the value in place; [check `mutate_inplace` function in this answer](http://stackoverflow.com/questions/33820971/haskell-use-last-reference-to-a-variable-to-efficiently-create-a-new-variable/33827943#33827943) – behzad.nouri Feb 25 '16 at 01:15
  • @behzad.nouri: thanks for this reference, but I'll leave my answer in place, because I think that falls under the `do` magic I mentioned. – fjarri Feb 25 '16 at 01:19
  • 4
    Why do you want to do this? References go against the grain of the Haskell model. Spend your effort instead on learning to think as a functional programmer. Anyway, speaking as a jobbing C# programmer, `ref` and `out` are among my least favourite things in the language; Haskell doesn't support them and I say good riddance. – Benjamin Hodgson Feb 25 '16 at 01:28
  • 2
    Indeed, this is probably the *worst* way to deal with multiple return values. Just return a record or even a tuple. It has its uses for arrays/vectors. – dfeuer Feb 25 '16 at 02:04
  • Record update syntax may actually be exactly what you're looking for. – dfeuer Feb 25 '16 at 02:08

4 Answers4

10

There is no difference between "pass-by-value" and "pass-by-reference" in languages like Haskell and ML, because it's not possible to assign to a variable in these languages. It's not possible to have "changes to a method parameter" in the first place in influence any passed variable.

newacct
  • 119,665
  • 29
  • 163
  • 224
6

It depends on context. Without any context, no, you can't (at least not in the way you mean). With context, you may very well be able to do this if you want. In particular, if you're working in IO or ST, you can use IORef or STRef respectively, as well as mutable arrays, vectors, hash tables, weak hash tables (IO only, I believe), etc. A function can take one or more of these and produce an action that (when executed) will modify the contents of those references.

Another sort of context, StateT, gives the illusion of a mutable "state" value implemented purely. You can use a compound state and pass around lenses into it, simulating references for certain purposes.

dfeuer
  • 48,079
  • 5
  • 63
  • 167
5

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)?

No, values in Haskell are immutable (well, the do notation can create some illusion of mutability, but it all happens inside a function and is an entirely different topic). If you want to change the value, you will have to return the changed value and let the caller deal with it. For instance, see the random number generating function next that returns the value and the updated RNG.

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

Consequently, you can't have out either. If you want to return several entirely disconnected values (at which point you should probably think why are disconnected values being returned from a single function), return a tuple.

fjarri
  • 9,546
  • 39
  • 49
0

No, it's not possible, because Haskell variables are immutable, therefore, the creators of Haskell must have reasoned there's no point of passing a reference that cannot be changed.

consider a Haskell variable:

let x = 37

In order to change this, we need to make a temporary variable, and then set the first variable to the temporary variable (with modifications).

let tripleX = x * 3
let x = tripleX

If Haskell had pass by reference, could we do this?
The answer is no.

Suppose we tried:

tripleVar :: Int -> IO()

tripleVar var = do

  let times_3 = var * 3
  let var = times_3


The problem with this code is the last line; Although we can imagine the variable being passed by reference, the new variable isn't.
In other words, we're introducing a new local variable with the same name;

Take a look again at the last line:

let var = times_3

Haskell doesn't know that we want to "change" a global variable; since we can't reassign it, we are creating a new variable with the same name on the local scope, thus not changing the reference. :-(


tripleVar :: Int -> IO()

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

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

Sapphire_Brick
  • 1,560
  • 12
  • 26