Search code examples
c++haskelllambdaghc

How GHC captures the enviroment of variables when lambda expressions are used by value or by reference?


In this stackoverflow post there is code in C++ that tries to mimic associated types. When the lambda functions capture the environment(closure) using by reference capture the code compiles but fails at runtime. When the code changed to capture by value the code succeeds both at compile time and runtime. How GHC captures the closure of a lambda function, by reference or by value?


Solution

  • GHC captures variables in the closure by reference, but (1) because all values are allocated on a garbage collected heap, the reference remains valid for the lifetime of the closure, so there will be no runtime error as in your C++ example; and (2) because Haskell values are immutable, the behavior of the program is basically the same as if the closure had been captured by value, since the values of references don't change over the lifetime of Haskell programs.

    So, for example, in the program:

    subtracter :: Integer -> (Integer -> Integer)
    subtracter delta = let increment = -delta in \x -> x + increment
    

    the result of a call subtracter 42 is a lambda x -> x + increment that has captured the value of increment by reference. Even though increment was a "local variable" (or as close as one gets to a local variable in Haskell), it is still a reference is to an immutable value -42 on the heap, not a mutable value on the stack, as it would be with C++. So, the reference will remain valid for the lifetime of the lambda, and it will always be an immutable reference to the value -42, so the effect is the same as if the lambda had captured it "by value" as -42.