I am studying Haskell and I am learning what is an abstraction, substitution (beta equivalence), application, free and bound variables (alpha equivalence), but I have some doubts resolving these exercises, I don't know if my solutions are correct.
Make the following substitutions
1. (λ x → y x x) [x:= f z]
Sol. (\x -> y x x) =>α (\w -> y w w) =>α (\w -> x w w) =>β (\w -> f z w w)
2. ((λ x → y x x) x) [y:= x]
Sol. ((\x -> y x x)x) =>α (\w -> y w w)[y:= x] = (\w -> x w w)
3. ((λ x → y x) (λ y → y x) y) [x:= f y]
Sol. aproximation, i don't know how to do it: ((\x -> y x)(\y -> y x) y) =>β
(\x -> y x)y x)[x:= f y] =>β y x [x:= f y] = y f y
4. ((λ x → λ y → y x x) y) [y:= f z]
Sol aproximation, ((\x -> (\y -> (y x x))) y) =>β ((\y -> (y x x)) y) =>α ((\y -> (y x x)) f z)
Another doubt that I have is if can I run these expressions on this website? It is a Lambda Calculus Calculator but I do not know how to run these tests.
1. (λ x → y x x) [x:= f z]
Sol. (\x -> y x x) =>α (\w -> y w w) =>α (\w -> x w w) =>β (\w -> f z w w)
No, you can't rename y, it's free in (λ x → y x x). Only bound variables can be (consistently) α-renamed. But only free variables can be substituted, and there's no free x in that lambda term.
2. ((λ x → y x x) x) [y:= x]
Sol. ((\x -> y x x)x) =>α (\w -> y w w)[y:= x] = (\w -> x w w)
Yes, substituting x for y would allow it to be captured by the λ x, so you indeed must α-rename the x in (λ x → y x x) first to some new unique name as you did, but you've dropped the application to the free x for some reason. You can't just omit parts of a term, so it's ((\w -> y w w) x)[y:= x]. Now perform the substitution. Note you're not asked to perform the β-reduction of the resulting term, just the substitution.
I'll leave the other two out. Just follow the rules carefully. It's easy if you rename all bound names to unique names first, even if the renaming is not strictly required, for instance
((λ x → y x) (λ y → y x) y) [x:= f y] -->
((λ w → y w) (λ z → z x) y) [x:= f y]
The "unique" part includes also the free variables used in the substitution terms, that might get captured after being substituted otherwise (i.e. without the renaming being performed first, in the terms in which they are being substituted). That's why we had to rename the bound y in the above term, -- because y appears free in the substitution term. We didn't have to rename the bound x but it made it easier that way.
In A tutorial on universality and expressiveness of fold chapter 4.1, it states that this pattern of recursion
h y [] = f y
h y (x:xs) = g y x xs (h y xs)
is primitive recursion, but I don't understand why the pattern
h [] = v
h (x:xs) = g x (h xs)
is not primitive recursion according to the definition of primitive recursive.
The value of h y' is still based on h y in the h (x:xs) = g x (h xs) if we let y = xs and y' = x:xs.
The primitive recursion scheme is parametric on the choice of f,g
h y [] = f y
h y (x:xs) = g y x xs (h y xs)
That is, we are free to choose f,g as we want, and h will be defined through primitive recursion.
In particular, we can choose
f = \y -> v
g = \y x xs -> g' x z
where g' is any other function picked by us. We then get
h y [] = v
h y (x:xs) = g' x (h y xs)
Now, if we let
h' xs = h () xs
we fix the y argument to an immaterial value so to recover the function in the question. Pedantically, h' is not obtained directly as an instance of the general form, so h' is technically not defined through the primitive recursion scheme seen above (i.e., it is not an instance of that). Sometimes, instead of y we find there many variables y1 .. yn allowing us to pick n=0 and remove the y as we want in this case.
I think I understand the monad concept in Haskell, i.e., the role of >>= and return. However, I'm a little confused by the the syntax of the application of them in this Wikipedia example.
add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my = -- Adds two values of type (Maybe Int), where each input value can be Nothing
mx >>= (\x -> -- Extracts value x if mx is not Nothing
my >>= (\y -> -- Extracts value y if my is not Nothing
return (x + y))) -- Wraps value (x+y), returning the sum as a value of type (Maybe Int)
I understand clearly the intent of this function. I'm just a little confused about the order of evaluation. May anyone show line by line which part of the function is evaluated (supposing that mx and my are of type Maybe Int and mx = Just x' and my = Just y', where x' and y' are Int values)?
I think it is something like that:
mx >>= (\x -> my >>= (\y -> return (x + y))) --- original
(\x -> my >>= (\y -> return (x + y))) x --- mx is Just Int, then apply the function in x
(\x -> my >>= (\y -> return (x + y))) --- x is the first argument. Then I get confused. What's the second part of the function?
n.m. gave the key for the answer, as I was replacing incorrectly the values.
We have to apply beta reduction.
Quoting the Haskell Wiki:
For example, suppose we apply the function
(\x -> 2*x*x + y) to the value 7. To calculate the result, we
substitute 7 for every free occurrence of x, and so the application of
the function (\x -> 2*x*x + y)(7) is reduced to the result
2*7*7 + y
(http://www.haskell.org/haskellwiki/Beta_reduction)
Then, applying that to the function I presented,
mx >>= (\x -> my >>= (\y -> return (x + y)))
(\x -> my >>= (\y -> return (x + y))) x'
my >>= (\y -> return (x' + y)))
(\y -> return (x' + y)) y'
return (x' + y')
In programming language J, is a train of verbs always associative? If it is, Are there any proofs?
No, a train of verbs is not associative and this follows the definitions. For example, a fork is
(f g h) y = (f y) g (h y)
but
(f (g h)) y = y f ((g h) y) = y f (y g (h y))
which can also be written as y f y g h y. And
((f g) h) y = y (f g) (h y) = y f (g (h y))
which can also be written as y f g h y.
Those three are completely different things.
Train in J is right associative, and the minimum group is a fork. Only when it cannot make a fork, it makes a hook. So
vvvvv = (vv(vvv)),
And
vvvv= (v(vvv)).
While studying for a Functional Programming exam, I came across the following questions from a previous test:
t2 = (\x -> \y -> \z -> (x y, x (x z)))
t3 = t2 (take 3 . reverse) mnr mnr
For t2, it is asked to determine the most general type of the statement. The answer appears to be:
(a -> a) -> a -> a -> (a,a)
I am able to find the answer by entering the statement into WinHugs, but how is this answer found? I understand from my previous post that it has something to do with lambda functions though other than that I am at a loss to explain what is going on here.
The second part of the question (t3) then applies two functions to two instances of the variable mnr. For mnr = [0,1,2,3,4,5,6] this results in:
([6,5,4],[4,5,6])
How does this work? The functions take and reverse are clear but how are they applied to the lambda functions in t2?
Let's start from the middle, at the result.
(x y, x (x z))
because x is being applied to things (y, z, and x z), we know it has the type (a -> ?) where the question mark represents an unknown type. Now, the result of x is being passed to x in x (x z), so its input type must be its output type:
x :: a -> a
Now, x is applied to y and to z, so they both must be of type a. x y and x (x z) are also both of type a (as that is x's return type), so t2 returns something of type (a, a).
Putting this together with the type of its arguments (x, y, and z), we get that is has type
(a -> a) -- x's type
-> a -- y's type
-> a -- z's type
-> (a, a) -- the result type
For you second question, let's first look at what things are bound to what variables in t2's definition. The first argument is x, so in this case
x = (take 3 . reverse)
The next argument is y, so
y = mnr
Similarly for z,
z = mnr
The result will be (x y, x (x z)), so let's evaluate this
(x y, x (x z))
= ((take 3 . reverse) mnr, (take 3 . reverse) ((take 3 . reverse) mnr))
= (take 3 (reverse mnr), take 3 (reverse (take 3 (reverse mnr))))
with this specific case of mnr = [0,1,2,3,4,5,6], we get
= (take 3 (reverse [0,1,2,3,4,5,6]), take 3 (reverse (take 3 (reverse [0,1,2,3,4,5,6]))))
= (take 3 [6,5,4,3,2,1,0], take 3 (reverse (take 3 [6,5,4,3,2,1,0])))
= ([6,5,4], take 3 (reverse [6,5,4]))
= ([6,5,4], take 3 [4,5,6])
= ([6,5,4], [4,5,6])
t2 = (\x -> \y -> \z -> (x y, x (x z)))
Notice the applications at the end. x is applied to y, so x must be a function. x is also applied to (x z), so x must return the same type that it takes as argument.
I am not sure what you mean with the second question. Two instances of mnr?
EDIT:
So, t3 is simply t2 applied to the arguments (take 3 . reverse) mnr mnr. The first argument is what was known as x in t2, and we saw in the above that x was applied to y and then (x z).
The result is then ((take 3 . reverse) mnr, (take 3 . reverse) ((take 3 . reverse) mnr))
The mnr in the first part of the tuple is the first mnr passed as an argument (y). The one in the second part is the second argument (z). Of course, they are the same.