Scope of variables in lambda calculus / haskell - haskell

Given an expression like s := (λx, y, z.x y z) λx, y.x λy, z.z, is the scope of the bound variables
s := (λx, y, z.x y z) (λx, y.x) (λy, z.z)
or
s := (λx, y, z.x y z) (λx, y.x (λy, z.z))
I am guessing it is the 2nd option.

This question is basically unanswerable. It would be easy to define a concrete syntax with either proposed abstract syntax tree, and I don't really think there's such a strong convention one way or the other that you would want to assume one without seeing explicit text in the syntax definition for the document you were reading.
Since this is explicitly tagged Haskell: in this specific case it is simply a parse error, and you are required to add parentheses to disambiguate. Without the first \x y z -> x y z function, though, the default would be to parse as \x y -> (x (\y z -> z)), and you would need to add parentheses to get the other option of (\x y -> x) (\y z -> z). (The parentheses around \y z -> z are not optional.)

Related

Why Haskell disrespects bound identifiers for pattern matching?

f x zero = Nothing
f x y = Just $ x / y
where zero = 0
The literal-bound identifier zero simply matches all after the warning Pattern match(es) are overlapped.
That's how Haskell's syntax works; every lowercase-initial variable name in a pattern (re)binds that name. Any existing binding will be shadowed.
But even if that weren't the case, the binding for zero would not be visible to the first alternative, because of how Haskell's syntax works. A similar thing happens in the following version:
f = \v1 v2 -> case (v1, v2) of
(x, zero) -> Nothing
(x, y) -> Just $ x / y
where zero = 0
The where clause only applies to the one alternative that it's part of, not to the whole list of alternatives. That code is pretty much the same thing as
f = \v1 v2 -> case (v1, v2) of
(x, zero) -> Nothing
(x, y) -> let zero = 0 in Just $ x / y
If bound identifiers had different semantics than unbound identifiers in a pattern match, that could be quite error prone as binding a new identifier could mess up pattern matches anywhere that identifier is in scope.
For example let's say you're importing some module Foo (unqualified). And now the module Foo is changed to add the binding x = 42 for some reason. Now in your pattern match you'd suddenly be comparing the first argument against 42 rather than binding it to x. That's a pretty hard to find bug.
So to avoid this kind of scenario, identifier patterns have the same semantics regardless of whether they're already bound somewhere.
Because they are very fragile. What does this compute?
f x y z = 2*x + 3*y + z
Would you expect this to be equal to
f x 3 z = 2*x + 9 + z
f _ _ _ = error "non-exhaustive patterns!"
only because there's a y = 3 defined somewhere in the same 1000+ line module?
Also consider this:
import SomeLibrary
f x y z = 2*x + 3*y + z
What if in a future release SomeLibrary defines y? We don't want that to suddenly stop working.
Finally, what if there is no Eq instance for y?
y :: a -> a
y = id
f :: a -> (a -> a) -> a
f x y = y x
f x w = w (w x)
Sure, it is a contrived example, but there's no way the runtime can compare the input function to check whether it is equal to y or not.
To disambiguate this, some new languages like Swift uses two different syntaxes. E.g. (pseudo-code)
switch someValue {
case .a(x) : ... // compare by equality using the outer x
case .b(let x) : ... // redefine x as a new local variable, shadowing the outer one
}
zero is just a variable that occurs inside a pattern, just like y does in the second line. There is no difference between the two. When a variable that occurs inside a pattern, this introduces a new variable. If there was a binding for that variable already, the new variable shadows the old one.
So you cannot use an already bound variable inside a pattern. Instead, you should do something like that:
f x y | y == zero = Nothing
where zero = 0
f x y = Just $ x / y
Notice that I also moved the where clause to bring it in scope for the first line.

Lambda calculus beta reduction specific steps and why

From a book I'm recently reading:
First:
𝜆𝑧.(𝜆𝑚.𝜆𝑛.𝑚)(𝑧)((𝜆𝑝.𝑝)𝑧)
The outermost lambda binding 𝑧 is, at this point, irreducible because it has no argument to apply to. What remains is to go inside the terms one layer at a time until we find something reducible.
Next:
𝜆𝑧.(𝜆𝑛.𝑧)((𝜆𝑝.𝑝)𝑧)
We can apply the lambda binding 𝑚 to the argument 𝑧. We keep searching for terms we can apply. The next thing we can apply is the lambda binding 𝑛 to the lambda term ((𝜆𝑝.𝑝)𝑧).
I don't get it. In the first section, it says 𝜆𝑧 has no argument to apply to, that I can probably understand, but then at the Next section I think the z can be bound to ((𝜆𝑝.𝑝)𝑧) because as you can see, 𝜆𝑧.(𝜆𝑛.𝑧), the body of 𝜆𝑧 clearly has a z argument which can be bound. But the book just ignored the head 𝜆𝑧 and directly bound n to ((𝜆𝑝.𝑝)𝑧). I mean 𝜆𝑛.𝑧 doesn't have an n argument, why does it get to be bound?
Can somebody explain to me about this?
Using normal order evaluation, you can get the answer in two beta reductions
// beta reduction 1
λz.(λm.λn.m)(z)((λp.p)z) →β (λn.m) [m := z]
λz.(λm.λn.z)(z)((λp.p)z)
// beta reduction 2
λz.(λn.z)((λp.p)z) →β z [n := ((λp.p)z)]
λz.(λn.z)((λp.p)z)
// result
λz.z
The second reduction might seem tricky because n is bound to ((λp.p)z) but the expression is just z, so n is thrown away.
Using applicative order evaluation, it takes one extra step
// beta reduction 1
λz.(λm.λn.m)(z)((λp.p)z) →β p [p := z]
λz.(λm.λn.m)(z)((λp.z)z)
// beta reduction 2
λz.(λm.λn.m)(z)(z) →β (λn.m) [m := z]
λz.(λm.λn.z)(z)(z)
// beta reduction 3
λz.(λn.z)(z) →β z [n := z]
λz.(λn.z)(z)
// result
λz.z
In this scenario, whether we use normal order evaluation or applicative order evaluation, the result is the same. Differing evaluation strategies sometimes evaluate to different results.
An important note, the reduction steps we've done above will not take place until λz is applied (depending on the implementation). In the example code you have provided, λz is never applied, therefore simplifying λz's term is just for exercise, in this case.
All we've done is demonstrate lambda equivalence (under two different evaluation strategies)
λz.(λm.λn.m)(z)((λp.p)z) <=> λz.z
Lambda notation is a bit weird to parse. IMO Haskell syntax is clearer:
\z -> (\m -> \n -> m) z ((\p -> p) z)
or, even more explicit
\z -> (
(
( \m -> (\n -> m) )
z
)
( (\p -> p) z )
)
The first reduction step is
\z -> (
(
(\n -> z)
)
( (\p -> p) z )
)
or
\z -> (
(\n -> z)
( (\p -> p) z )
)
then you can indeed bind ((\p -> p) z) – not to z but to n! (Which isn't actually used at all though.)
\z -> (
(z)
)
or simply \z -> z. So, we still have that z lambda, which as the book said is irredicible. We just don't have anything else!
...I'm not sure if that was actually your question. If it was rather: why must we not first see if we can reduce ((\p -> p) z), then the answer is, I think, lambda calculus as such doesn't define this at all (it just defines what transformation you can apply, not in which order you should do it.Actually I'm not sure about this, correct me if I'm wrong). In a strict language like Scheme, you would indeed first reduce ((\p -> p) z); Haskell wouldn't do that since there's no need. Either way, it doesn't really matter, because the result is discarded anyway.
( \z -> (\n -> z) ((\p -> p) z) )
≡ ( \z -> (\n -> z) z )
≡ ( \z -> (\n -> z) foo )
≡ ( \z -> z )
The key is that n is never used in the abstraction. n is still bound to ((λp.p)z), but it is immediately discarded.
λz.(λm.λn.m)(z)((λp.p)z) = λz.(λn.z)((λp.p)z) Replacing m with z
= λz.z Replacing n with ((λp.p)z)

Is the following code really currying in haskell?

I am trying to understand currying by reading various blogs and stack over flow answers and I think I understood some what. In Haskell, every function is curried, it means, when you have a function like f x y = x + y
it really is ((f x) y)
in this, the function initially take the first parameter 'x' as the parameter and partially applies it to function f which in turn returns a function for y. where it takes just y a single parameter and applies the function. In both cases the function takes only one parameter and also the process of reducing a function to take single parameter is called 'currying'. Correct me if my understanding wrong here.
So if it is correct, could you please tell me if the functions 'two' and 'three' are curried functions?
three x y z = x + y + z
two = three 1
same = two 1
In this case, I have two specialized functions, 'two' and 'same' which are reduced to take only one parameter so is it curried?
Let's look at two first.
It has a signature of
two :: Num a => a -> a -> a
forget the Num a for now (it's only a constraint on a - you can read Int here).
Surely this too is a curried function.
The next one is more interesting:
same :: Num a => a -> a
(btw: nice name - it's the same but not exactly id ^^)
TBH: I don't know for sure.
The best definition I know of a curried function is this:
A curried function is a function of N arguments returning another function of (N-1) arguments.
(if you want you can extent this to fully curried functions of course)
This will only fit if you define constants as functions with 0 parameters - which you surely can.
So I would say yes(?) this too is a curried function but only in a mathy borderline way (like the sum of 0 numbers is defined to be 0)
Best just think about this equationally. The following are all equivalent definitions:
f x y z = x+y+z
f x y = \z -> x+y+z
f x = \y -> (\z -> x+y+z)
f = \x -> (\y -> (\z -> x+y+z))
Partial application is only tangentially relevant here. Most often you don't want the actual partial application to be performed and the actual lambda object to be created in memory - hoping instead that the compiler will employ - and optimize better - the full definition at the final point of full application.
The presence of the functions curry/uncurry is yet another confusing issue. Both f (x,y) = ... and f x y = ... are curried in Haskell, of course, but in our heads we tend to think about the first as a function of two arguments, so the functions translating between the two forms are named curry and uncurry, as a mnemonic.
You could think that three function with anonymous functions is:
three = \x -> (\y -> (\z -> x + y + z)))

Error while declaring a lambda function: declare an instance first

I am trying to understand lambda functions (i.e. anonymous functions) in Haskell by writing a few simple functions that use them.
In the following example, I am simply trying to take in 3 parameters and add two of the three using an anonymous function and adding the third parameter after that.
I am getting an error saying that I must declare an instance first.
specialAdd x y z = (\x y -> x + y) + z
I appreciate any explanation of why my example is not working and/or any explanation that would help me better understand lambda functions.
specialAdd x y z = (\x y -> x + y) + z
In this example, what you are trying to do is add a function to a number, which is not going to work. Look at (\x y -> x + y) + z: it has the form a + b. In order for such an expression to work, the a part and the b part must be numbers of the same type.
Haskell is a bit of an unusual language, so its error messages are rarely of the form "you can't do that". So what's going on here is that Haskell sees that (\x y -> x + y) is a function, and since in an expression like a + b, b must be the same type as a, it concludes that b must also be a function. Haskell also allows you to define your own rules for adding non-built-in types; so it can't just give you an error saying "you can't add two functions," but instead the error is "you have not defined a rule that allows me to add two functions."
The following would do what you want:
specialAdd x y z = ((\x y -> x + y) x y) + z
Here you are applying the function (\x y -> x + y) to arguments x and y, then adding the result to z.
A good way to practice anonymous function is to use them with high order function as fold or map.
Using map as an entry point,
Basic definition of map,
map f [] = []
map f (x:xs) = f x : f xs
Built up an example,
>>> let list = [0..4]
>>> let f x = x + 1
Applying map we obtain,
>>> map f list
[1,2,3,4,5]
Now, we can omit the declaration of f and replace it using anonymous function,
>>> map (\x->x+1) list
[1,2,3,4,5]
then we deduce, map f list == map (\x->x+1) list, thus
f = \x-> x + 1 --- The same as f x = x + 1, but this is the equivalent lambda notation.
then starting with a simple function we see how to translate it into an anonymous function and then how an anonymous function can be rely to a lambda abstraction.
As an exercise try to translate f x = 2*x.
Now more complex, an anonymous function which take two arguments,
Again an working example,
>>> let add x y = x + y
>>> foldl' add 0 [0..4]
10
Can be rewrite using anonymous function as,
>>> foldl' (\x y -> x + y) 0 [0..4]
Again using equality we deduce that add = \x y -> x + y
Moreover as in hakell all function are function of one argument, and we can partial apply it, we can rewrite our previous anonymous function as, add = \x -> (\y -> x + y).
Then where is the trick ?? Because, I just show the use of anonymous function into high order one, and starting from that, showing how this can be exploited to rewrite function using lambda notation. I mean how can it help you to learn how to write down anonymous function ?
Simply cause I've give you (show you) an existing framework using high order function.
This framework is a huge opportunity to accommodate you with this notation.
Starting from that an infinity range of exercise can be deduce, for example try to do the following.
A - Find the corresponding anonymous function ?
1 - let f (x,y) = x + y in map f [(0,1),(2,3),(-1,1)]
2 - let f x y = x * y in foldl' f 1 [1..5]
B - Rewrite all of them using lambda notation into a declarative form (f = \x-> (\y-> ...)
And so on ....
To summarize,
A function as
(F0) f x1 x2 ... xn = {BODY of f}
can always be rewrite as,
(F1) f = \x1 x2 ... xn -> {BODY of f}
where
(F2) (\x1 x2 ... xn -> {BODY of f})
F2 form are just anonymous function, a pure translation of the function into lambda calculus form. F1 is a declarative lambda notation (because we declare f, as we define it, binding it to the anonymous F2). F0 being the usual notation of Haskeller.
A last note focusing on the fact we can put parenthesis between the argument, this create a closure. Doing that mean that a subset of the function's code can be fully evaluated using a subset of the function's argument, (mean converting to a form where no more free variable occurs), but that's another story.
Here is correct form:
specialAdd a b c = ((\x y -> x + y) a b) + c
Example from Learn You a Haskell...:
zipWith (\a b -> (a * 30 + 3) / b) [5,4,3,2,1] [1,2,3,4,5]
Great explanation:
http://learnyouahaskell.com/higher-order-functions#lambdas
From what I understand Labmbda/Anonymous functions help you declare a function "inline" without the need to give it a name. The "\" (ASCII for the Greek, λ) precedes the variable names for the expression that follows the "->". For example,
(\x y -> x + y)
is an anonymous (lambda) function similar to (+). It takes two parameters of type Num and returns their sum:
Prelude> :type (+)
(+) :: Num a => a -> a -> a
Prelude> :type (\x y -> x + y)
(\x y -> x + y) :: Num a => a -> a -> a
Your example is not working because, as others have pointed out, the right hand side of it is using a lambda function, (\x y -> x + y), as a parameter for the (+) operator, which is defined by default only for parameters of type Num. Some of the beauty of the lambda function can be in its "anonymous" use. Vladimir showed how you can use the lambda function in your declaration by passing it the variables from the left side. A more "anonymous" use could be simply calling it, with variables, without giving the function a name (hence anonymous). For example,
Prelude> (\x y z -> x + y + z) 1 2 3
6
and if you like writing parentheses:
Prelude> (((+).) . (+)) 1 2 3
6
Or in a longer expression (as in your example declaration), e.g.,
Prelude> filter (\x -> length x < 3) [[1],[1,2],[1,2,3]]
[[1],[1,2]]
You are trying to use (+) as something like (Num a) => (a -> a -> a) -> a -> ?? which is not correct.
(+) is defined in the class Num and (a -> a -> a) is not an instance of this class.
What exactly are you trying to achieve ?

Partial Application of Infix Functions in F#

In haskell it is posible to partially apply an infix function using sections, for instance given the infix function < (less than) one can partially apply any of the function's arguments: (5 <) , (< 5)
In other words, in haskell we have the following shorthand notation:
op :: a -> b -> c
(`op` y) === \x -> x `op` y
(x `op`) === \y -> x `op` y
Does F# have a similar concept?
No, neither of those (apart from standard partial application like (=) x).
Whereas I like the succinctness of Seq.find ((=) x), things like Seq.filter ((<) 3) (or even Seq.map (flip (-) 1)) are simply awkward to read and should immediately be replaced by a lambda expression, imo.
If you want to invent your own standards...
let lsection x f y -> f x y
let rsection f y x -> f x y
Then lsection 5 (<) === (5 <) and rsection (<) 5 === (< 5).
Though really, without language support, just put a lambda in there and it'll be clearer.

Resources