How does variable binding work with recursion in Haskell? - haskell

I was reading about Haskell and it stated that once a variable is bound to an expression it cannot be rebound for example
x = 10
x = 11
Assign.hs:2:1: error:
Multiple declarations of ‘x’
Declared at: Assign.hs:1:1
Assign.hs:2:1
So if this is the case... how is recursion working where the same variable keeps getting bound to other things? For example
drop n xs = if n <= 0 || null xs
then xs
else drop (n-1) (tail xs)
the variable n... is being bound again and again every time the function recurses. Why is this allowed?
Also if you guys could tell me some key words to search for so I can learn more about this myself I'd highly appreciate it.

Haskell has lexical scoping. When you declare a variable inside a scope, it hides any variable with the same name from an outer scope. For example, in the following program,
x :: Int
x = 5
main :: IO ()
main = do
x <- readLn :: IO Int
print x
If you compile with ghc -Wall, it will compile correctly, but give you the following warnings:
sx-scope.hs:2:1: warning: [-Wunused-top-binds]
Defined but not used: ‘x’
sx-scope.hs:6:10: warning: [-Wname-shadowing]
This binding for ‘x’ shadows the existing binding
defined at sx-scope.hs:2:1
So the x outside main and the x in main are different variables, and the one in the inner scope temporarily hides the one in the outer scope. (Okay, “temporarily” in this example means until main returns, which is as long as the program is running, but you get the concept.)
Similarly, when you declare drop n xs or \n xs ->, n and xs are local variables that only exist during that invocation of the function. It can be called more than once with different values of n and xs.
When a function is tail-recursive, that is, returns a call to itself, the compiler knows it is about to replace the old parameters, which were from a scope that no longer exists, with updated parameters of the same type. So it can re-use the stack frame and store the new parameters in the same locations as the previous ones. The resulting code can be as fast as iteration in a procedural language.

In almost any language, identifiers are only meaningful because they exist in a scope; conceptually a sort of implicit map from names to the things they denote.
In modern languages you usually have (at least) a global scope, and each local scopes associated with each function/procedure. Pseudocode example:
x = 1
print x
x = 2
print x
function plus_one(a):
b = 1
return a + b
print plus_one(x)
x is a name in the global scope, a and b are names in the local scope of the function plus_one.
Imperative languages (and non-pure declarative languages) are generally understood by thinking of those names as mapped to a sort of slot or pigeon hole, into which things can be stored by assignment, and the current connects referred to by using the name. This works only because an imperative step-by-step way of thinking about these programs gives us a way of understanding what "current" means.1 The above example shows this; x is first assigned 1, then printed, then assigned 2, then printed again; we'd expect this to print "1" and then print "2" (and then print "3" from the last line).
Given that understanding of variables as slots that can store things, it's easy to fall into the trap of thinking of the local variables that represent a function's arguments as just slots that get filled when you call the function. I say trap because this is not a helpful way of thinking about function arguments and calls, even in imperative languages. It more or less works as long as each function only ever has one call "in flight" at once, but introducing one of any number of common programming features breaks this model (recursion, concurrency, laziness, closures, etc). That's the misunderstanding at the heart of a number of questions I've seen here on SO, where the poster was having trouble understanding recursive calls, or wanted to know how to access the local variables of a function from outside, or etc.
You should actually think of a function as having a separate scope associated with each call of that function2. The function itself is kind of like a template for a scope, rather than a scope itself (although common language does usually talk about "the scope of a function" as shorthand). If you provided bindings for the function's parameters then you can produce a scope, but a typical function is called many times with different parameters, so there isn't just one scope for that function.
Consider my pseudocode plus_one, with argument a. You could imagine that a is a local name for a variable, and the call plus_one(x) just assigns the contents of x into the slot for a and then starts executing the code of plus_one. But I contend that it's better to think that when you call plus_one on x you're creating a new scope, in which there is a variable called a (containing with the contents of the global scope x at this point), but it is not "the" a variable.
This is vitally important for understanding recursion, even in imperative languages:
function drop(n, xs):
if n <= 0 || null(xs):
return xs
else:
return drop(n - 1, tail(xs))
Here we could try to imagine that there's only one xs variable, and when we make the recursive call to drop we're assigning the tail of the original xs to the xs variable and starting the function's code again. But that falls down as soon as we change it to something like:
function drop(n, xs):
if n <= 0 || null(xs):
return xs
else:
result = drop(n - 1, tail(xs))
print xs
return result
Now we're using xs after the recursive call. What this does is hard to explain if we're imagining that there's only one xs, but trivial if we think of there being a separate xs in a separate scope every time we call drop. When we make the recursive call to drop (passing it n - 1 and tail(xs)) it creates its own separate xs, so it's entirely unmysterious that print xs in this scope still can access xs.
So, is this story different with Haskell? It's true that the nature of variables is quite different in Haskell than from typical recursive languages. Instead of scopes mapping names to slots in which we can place different contents at different times, scopes map names directly to values, and there's no notion of time in which we could say an identifier "was" bound to one value (or was not bound to anything) and "now" is bound to a different value. x = 1 at global scope in Haskell isn't a step that "happens" and changes something, it's just a fact. x just is 1. Haskell isn't throwing an error at your x = 10 and x = 11 lines because the designers wanted to restrict you to only assigning a variable once, rather Haskell does not have a concept of assignment at all. x = 10 is giving a definition for x in that scope, and you can't have two separate definitions for the same name in the same scope.
The local scopes that come from functions in Haskell are the same; each name just is associated with a particular value3. But the actual values are parameterised on the values on which you call the function (they are quite literally a function of those values); each call has its own separate scope, with a different mapping from names to values. It's not that at each call n "changes" to become bound to the new argument, just that each call has a different n.
So recursion affects variable binding in Haskell in pretty much the same way it does in all major imperative languages. What's more, the extremely flippant way to describe how recursion affects name binding in all of these languages is to say "it doesn't". Recursion actually isn't special at all in this way; parameter passing, local scopes, etc, works exactly the same way when you call a recursive function as when you call an "ordinary" non-recursive functions, provided you understand the local scopes as being associated with each call of the function, not as a single thing associated with the function.
1 Sometimes even the scope mapping itself is mutable, and entries mapping names to slots can be added and removed as steps of the program. Python, for example, has a mutable global scope (in each module); you can add and remove module global variables dynamically, even with names determined from runtime data. But it uses immutable local scopes: a function's local variables exist even before they've been assigned a value (or after that value has been removed with del).
2 At least, this is how functions/procedures very common work in modern languages. It's not totally universal, but it's generally acknowledged to be a good way for functions/procedures to work.
3 Of course, thanks to laziness the particular value might be the bottom value, which is the "value" we pretend is the value of infinite loops and other forms of nontermination, so that we can interpret expressions as always having a value.

From https://en.wikibooks.org/wiki/Haskell/Variables_and_functions,
Within a given scope, a variable in Haskell gets defined only once and cannot change.
but scope isn't just the code of the function. Roughly, it's the code of function + its context, i.e. the arguments it's been called with, and anything from its outer scope. This is often referred to as a closure. Every time you call a function, the code runs under a new closure, and so the variables can evaluate to different things.
The recursive case isn't anything special with regards to this: a function being called twice by other code would run with a different closure, and its internal variables can evaluate to different things.

Related

Saving the result of applying a function to a variable in the same variable

I was remembering the haskell programming I learnt the last year and suddenly I had a little problem.
ghci> let test = [1,2,3,4]
ghci> test = drop 1 test
ghci> test
^CInterrupted.
I do not remember if it is possible.
Thanks!
test on the first line and test on the second line are not, in fact, the same variable. They're two different, separate, unrelated variables that just happen to have the same name.
Further, the concept of "saving in a variable" does not apply to Haskell. In Haskell, variables cannot be interpreted as "memory cells", which can hold values. Haskell's variables are more like mathematical variables - just names that you give to complex expressions for easier reasoning (well, this is a bit of an oversimplification, but good enough for now)
Consequently, variables in Haskell are immutable. You cannot change the value of a variable by assignment, like you can in many other languages. This property follows from interpreting the concept of "variable" in the mathematical sense, as described above.
Furthermore, definitions (aka "bindings") in Haskell are recursive. This means that the right side (the body) of a binding may refer to its left side. This is very handy for constructing infinite data structures, for example:
x = 42 : x
An infinite list of 42s
In your example, when you write test = drop 1 test, you're defining a list named test, which is completely unrelated to the list defined on the previous line, and which is equal to itself without the first element. It's only natural that trying to print such a list results in an infinite loop.
The bottom line is: you cannot do what you're trying to do. You cannot create a new binding, which shadows an existing binding, while at the same time references it. Just give it a different name.

Static Scoping vs Dynamic Scoping

Consider the following Ocaml code:
let app f y = let x = 4 in (f y)+1 ;;
let proc x = let change z = z-x in app change (x+3) ;;
(proc 2)
From what I understand, static scoping uses the structure of the code to determine the value of the variables, so in this case, x is replaced with 2 both in change and in (x+3). However, what I don't understand is why dynamic scoping only replaces the x in change with 4 but not the x in (x+3) with 4.
This is a bit confusing, I'm wondering if there's any trick to how to think through these problems.
A free variable is a variable that's used in a function but isn't defined in the function. In your example code, the only free variable is the variable x of the function change:
let change z = z - x
The function change uses x but doesn't define it.
The essence of scoping is to determine what variable definition a free variable is referring to, what its referent is. In your example code, it comes down to determining the referent of the free variable x in the change function.
For static scoping, there is a single static referent for every free variable. The referent is determined by looking outward in the text of the program through statically containing blocks of code until a binding (a definition) is found. In OCaml, variable bindings are introduced by function definitions and by let. So you're looking for the nearest enclosing block of change that binds x. The nearest binding of x is the function parameter x in let proc x =. For the example call, it has the value 2.
For dynamic scoping, the referent is determined by looking up through the nested function calls that are active at the time the value is required. In other words, you want to find the innermost function in the call chain that defines a variable named x. If you pretend that OCaml has dynamic scoping (which it most definitely does not), the call chain looks like this:
proc => app => change
The function just outside change in the call chain is app, and it defines a variable named x. So for the example code, the free variable x of change refers to the variable x defined by app. In the example, it has the value 4.
The x in x + 3 is not a free variable. It's defined by proc and is used in proc. For the example call it has the value 2 no matter what scoping is used.
For what it's worth I don't think it's particularly useful to think of replacing variables with values. It's better to think of them as being bound to values.
I'd also like to say (though I probably shouldn't) that dynamic scoping is insane. The extra flexibility is definitely not worth the extra complexity in figuring out what's going on. It shouldn't be necessary to trace through chains of function calls to determine the binding of a variable. (In my opinion.)

Implementing pass-by-reference argument semantics in an interpreter

Pass-by-value semantics are easy to implement in an interpreter (for, say, your run-of-the-mill imperative language). For each scope, we maintain an environment that maps identifiers to their values. Processing a function call involves creating a new environment and populating it with copies of the arguments.
This won't work if we allow arguments that are passed by reference. How is this case typically handled?
First, your interpreter must check that the argument is something that can be passed by reference – that the argument is something that is legal in the left-hand side of an assignment statement. For example, if f has a single pass-by-reference parameter, f(x) is okay (since x := y makes sense) but f(1+1) is not (1+1 := y makes no sense). Typical qualifying arguments are variables and variable-like constructs like array indexing (if a is an array for which 5 is a legal index, f(a[5]) is okay, since a[5] = y makes sense).
If the argument passes that check, it will be possible for your interpreter to determine while processing the function call which precise memory location it refers to. When you construct the new environment, you put a reference to that memory location as the value of the pass-by-reference parameter. What that reference concretely looks like depends on the design of your interpreter, particularly on how you represent variables: you could simply use a pointer if your implementation language supports it, but it can be more complex if your design calls for it (the important thing is that the reference must make it possible for you to retrieve and modify the value contained in the memory location being referred to).
while your interpreter is interpreting the body of a function, it may have to treat pass-by-referece parameters specially, since the enviroment does not contain a proper value for it, just a reference. Your interpreter must recognize this and go look what the reference points to. For example, if x is a local variable and y is a pass-by-reference parameter, computing x+1 and y+1 may (depending on the details of your interpreter) work differently: in the former, you just look up the value of x, and then add one to it; in the latter, you must look up the reference that y happens to be bound to in the environment and go look what value is stored in the variable on the far side of the reference, and then you add one to it. Similarly, x = 1 and y = 1 are likely to work differently: the former just goes to modify the value of x, while the latter must first see where the reference points to and modify whatever variable or variable-like thing (such as an array element) it finds there.
You could simplify this by having all variables in the environment be bound to references instead of values; then looking up the value of a variable is the same process as looking up the value of a pass-by-reference parameter. However, this creates other issues, and it depends on your interpreter design and on the details of the language whether that's worth the hassle.

Call by need: When is it used in Haskell?

http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_need says:
"Call-by-need is a memoized version of call-by-name where, if the function argument is evaluated, that value is stored for subsequent uses. [...] Haskell is the most well-known language that uses call-by-need evaluation."
However, the value of a computation is not always stored for faster access (for example consider a recursive definition of fibonacci numbers). I asked someone on #haskell and the answer was that this memoization is done automatically "only in one instance, e.g. if you have `let foo = bar baz', foo will be evaluated once".
My questions is: What does instance exactly mean, are there other cases than let in which memoization is done automatically?
Describing this behavior as "memoization" is misleading. "Call by need" just means that a given input to a function will be evaluated somewhere between 0 and 1 times, never more than once. (It could be partially evaluated as well, which means the function only needed part of that input.) In contrast, "call by name" is simply expression substitution, which means if you give the expression 2 + 3 as an input to a function, it may be evaluated multiple times if the input is used more than once. Both call by need and call by name are non-strict: if the input is not used, then it is never evaluated. Most programming languages are strict, and use a "call by value" approach, which means that all inputs are evaluated before you begin evaluating the function, whether or not the inputs are used. This all has nothing to do with let expressions.
Haskell does not perform any automatic memoization. Let expressions are not an example of memoization. However, most compilers will evaluate let bindings in a call-by-need-esque fashion. If you model a let expression as a function, then the "call by need" mentality does apply:
let foo = expression one in expression two that uses foo
==>
(\foo -> expression two that uses foo) (expression one)
This doesn't correctly model recursive bindings, but you get the idea.
The haskell language definition does not define when, or how often, code is invoked. Infinite loops are defined in terms of 'the bottom' (written ⊥), which is a value (which exists within all types) that represents an error condition. The compiler is free to make its own decisions regarding when and how often to evaluate things as long as the program (and presence/absence of error conditions, including infinite loops!) behaves according to spec.
That said, the usual way of doing this is that most expressions generate 'thunks' - basically a pointer to some code and some context data. The first time you attempt to examine the result of the expression (ie, pattern match it), the thunk is 'forced'; the pointed-to code is executed, and the thunk overwritten with real data. This in turn can recursively evaluate other thunks.
Of course, doing this all the time is slow, so the compiler usually tries to analyze when you'd end up forcing a thunk right away anyway (ie, when something is 'strict' on the value in question), and if it finds this, it'll skip the whole thunk thing and just call the code right away. If it can't prove this, it can still make this optimization as long as it makes sure that executing the thunk right away can't crash or cause an infinite loop (or it handles these conditions somehow).
If you don't want to have to get very technical about this, the essential point is that when you have an expression like some_expensive_computation of all these arguments, you can do whatever you want with it; store it in a data structure, create a list of 53 copies of it, pass it to 6 other functions, etc, and then even return it to your caller for the caller to do whatever it wants with it.
What Haskell will (mostly) do is evaluate it at most once; if it the program ever needs to know something about what that expression returned in order to make a decision, then it will be evaluated (at least enough to know which way the decision should go). That evaluation will affect all the other references to the same expression, even if they are now scattered around in data structures and other not-yet-evaluated expressions all throughout your program.

Access the configuration parameters through a monad?

Quote from here: http://www.haskell.org/haskellwiki/Global_variables
If you have a global environment,
which various functions read from (and
you might, for example, initialise
from a configuration file) then you
should thread that as a parameter to
your functions (after having, very
likely, set it up in your 'main'
action). If the explicit parameter
passing annoys you, then you can
'hide' it with a Monad.
Now I'm writing something that needs access to configuration parameters and I wonder if someone could point me to a tutorial or any other resource that describes how monads can be used for this purpose. Sorry if this question is stupid, I'm just starting to grok monads. Reading Mike Vainer's tutorial on them now.
The basic idea is that you write code like this:
main = do
parameters <- readConfigurationParametersSomehow
forever $ do
myData <- readUserInput
putStrLn $ bigComplicatedFunction myData parameters
bigComplicatedFunction d params = someFunction params x y z
where x = function1 params d
y = function2 params x d
z = function3 params y
You read the parameters in the "main" function with an IO action, and then pass those parameters to your worker function(s) as an extra argument.
The trouble with this style is that the parameter block has to be passed down to every little function that needs to access it. This is a nuisance. You find that some function ten levels down in the call tree now needs some run-time parameter, and you have to add that run-time parameter as an argument to all the functions in between. This is known as tramp data.
The monad "solution" is to embed the run-time parameter in the Reader Monad, and make all your functions into monadic actions. This gets rid of the explicit tramp data parameter, but replaces it with a monadic type, and under the hood this monad is actually doing the data tramping for you.
The imperative world solves this problem with a global variable. In Haskell you can sort-of do the same thing like this:
parameters = unsafePerformIO readConfigurationParametersSomehow
The first time you use "parameters" the "readConfigurationParametersSomehow" gets executed, and from then on it behaves like a constant value, at least as long as your program is running. This is one of the few righteous uses for unsafePerformIO.
However if you find yourself needing such a solution then you really need to have a think about your design. Odds are you are not thinking hard enough about generalising your functions lower down; if some previously pure function suddenly needs a run-time parameter then look at the reason and see if you can exploit higher order functions in some way. For instance:
Pass down a function built using the parameter rather than the parameter itself.
Have the worker function at the bottom return a function as a result, which gets
passed up to be composed with a parameter-based function at the higher level.
Refactor your call stack so that fundamental operations are done by lower level
primitives at the bottom which are composed in a parameter-dependent way at the top.
Either way is going to involve

Resources