lambda calculus example quenstion - lambda-calculus

(λy.x z)c
I think a answer about this problem is x z.
If it is correct, why (λy.x z)c = x c is incorrect?
In this case, I refer to (λy.x z) = (λy.x)z = x. So I calculate it in the parenthesis first.

(λy.x z) c is not a problem, it is a λ-term.
You refer to λy.x z = (λy.x) z but there is no way to move the parentheses, otherwise it would mean they were useless.
λy. x z
Means the function which takes y as argument and returns x applied to z.
While (λy.x) z means the function which takes y as argument and returns x, the whole thing applied to z. Why would those two things be the same?
(They are not.)

Related

Fixing arguments when using pmap in Julia

I have defined a function f(x, y, z) in Julia and I want to parallely compute f for many values of x, holding y and z fixed. What is the "best practices" way to do this using pmap?
It would be nice if it was something like pmap(f, x, y = 5, z = 8), which is how the apply family handles fixed arguments in R, but it doesn't appear to be as simple as that. I have devised solutions, but I find them inelegant and I doubt that they will generalize nicely for my purposes.
I can wrap f in a function g where g(x) = f(x, y = 5, z = 8). Then I simply call pmap(g, x). This is less parsimonious than I would like.
I can set 5 and 8 as default values for y and z when f is defined and then call pmap(f, x). This makes me uncomfortable in the case where I want to fix y at the value of some variable a, where a has (for good reason) not been defined at the time that f is defined, but will be by the time f is called. It works, but it kind of spooks me.
A good solution, which turns your apparently inflexible first option into a flexible one, is to use an anonymous function, e.g.
g(y, z) = x -> f(x, y, z)
pmap(g(5, 8), x)
or just
pmap(x -> f(x, 5, 8), x)
In Julia 0.4, anonymous functions have a performance penalty, but this will be gone in 0.5.

Simplifying in Prolog

This is a simple mini program I have here that simplifies addition expressions that are queried. I can't seem to figure out how to finish it off. When I query the following:
sim(sum(sum(x,1),5),Val,[x:X]).
My result is Val = X+1+5. I would like it to simplify all the way to X+6.
Here is the code:
sim(Var, Value, Lst) :- member(Var:Value, Lst).
sim(Num, Num, _) :- number(Num).
sim(sum(Left, Right), Value, Lst) :-
sim(Left, LeftVal, Lst),
sim(Right, RightVal, Lst),
so(Value,LeftVal,RightVal).
so(Result, X, Y) :-
number(X),
number(Y), !,
Result is X + Y.
so(Result, X, Y) :- // debugging so(Result,_,Y) :-
Result = X + Y. // Y value write(Y), Result = Y.
What I do know is that my program is trying to simplify X+1 before adding X+1 and 5. When I change the last line of my "so" method to only give Y to Result I get Val = 6. Before that line I write Y to the screen for debugging purposes and it gives me 1 5 because of the recursion. Which means X must be a var? Is there a corner case not here that will allow me to simplify addition all the way down?
What I am noticing is that "so" never adds 1 and 5 because they are never arguments together in the "so" method that checks for X and Y to be numbers. X and 1 are the first arguments, then upon recursion X+1 and 5 are the arguments and it doesn't execute because number(X) fails when X is X+1
Expanding on my comment above: here is an example of an expression simplifier that separates 'symbols' from 'values' using two lists.
Notice how it uses the fact, in parsing and unparsing, that the only operator joining symbols and values is +.

What is best practices in Prolog when assigning a number to a variable?

To illustrate the difference between 'is' and '=', next example is given in my Prolog course:
?- X is 2+3
X = 5.
?- X = 2+3.
X = 2+3.
However, both Y is 3 and Y = 3 seem to do the same. Is there a difference? And if not, is there a convention not to use one of the two in Prolog programs?
In Prolog, =/2 and is/2 serve very different purposes. is/2 is used to assign a value from an arithmetic expression. The right hand side must be fully instantiated (all variables bound) and it will compute the expression and unify it with the single variable on the left. For example:
Y = 3,
X is log(Y+7)/2.
X = 1.151292546497023
Y = 3
The = is used to unify terms on each side of the =. So when you say:
X = log(Y+7)/2.
That is unifying the term X with the term log(Y+7)/2 (or, technically, '/'(log('+'(Y,7),2)) which gives you X = log(Y+7)/2. It doesn't compute log(Y+7)/2. because that's not the job of =. That's a job for is/2.
With = you can also say things like:
foo(X, _) = foo(3, blah).
And you will get X = 3 since it can unify both terms by setting X to 3.
In the simplest case, these operators appear to be the same because X is 3 evaluates the expression 3 and assigns it (binds it to) X, and X = 3 unifies X with 3. Both results are the same in this case.

Basic PROLOG counting

I'm new to prolog I'm trying to write a predicate which counts the following:
the predicates name is s2int when given:
s2int(0,Y) it shoud "return" Y=0.
s2int(s(0),Y) => Y=1.
s2int(s(s(0)),Y) => Y=2.
s2int(S(s(s(0))),Y) => Y=3.
and so on..
here is what i tried to write(very poorly),
at first i tried this code:
s2intAux(0,Y).
s2intAux(X,Y):- X = s(Z) ,Y1 is Y+1, s2intAux(Z,Y1).
but whenever i try to run it by typing s2intAux(s(0),Y) i get an error saying :"ERROR: is/2: Arguments are not sufficiently instantiated"
i get that error well because Y is undefined.
then i tried this one:
s2intAux(0,Y).
s2intAux(X,Y):- X = s(Z) ,Y1 is Y+1, s2intAux(Z,Y1).
s2int(X,Y):- Y1 is 0, s2intA(X,Y1).
(i tried to start Y with the value zero but this one didn't work at all)
I've been stuck for a couple of hours now which is why I'm turning to you guys, please help!
thank you.
You need the following to resolve the most trivial case:
s2intAux(0,0).
This will cause s2intAux(0,Y) to be true when Y is instantiated to 0.
In your subsequent lines, you don't have a statement that resolves Z to 0 when you run out of the s(.). For that, you need to take care of the single s(0) case. Then you can do the general case:
s2intAux(X,Y) :- X = s(0), Y is 1.
s2intAux(X,Y) :- X = s(Z), s2intAux(Z,Y1), Y is Y1 + 1.
Note that on the general case, we have to traverse down to get to the Y is 1 before we can unravel back up and finally assign Y to Y1 + 1.
You can also write that first line as just:
s2intAux(s(0),Y) :- Y is 1.
Final answer looks like this:
s2intAux(0,0).
s2intAux(s(0),Y) :- Y is 1.
s2intAux(X,Y) :- X = s(Z), s2intAux(Z,Y1), Y is Y1 + 1.

Unification in Prolog

This is a question from a past exam about unification in Prolog.
we were supposed to say if they unified and then the instantiations.
f(a,g(b,a)) and f(X,g(Y,X))
This unifies quite a = X, g(b,a) = g(Y,X) and is quite straight forward
f(g(Y),h(c,d)) and f(X,h(W,d))
I dont think this one unifies because of g(Y) =/ X, though h(c,d) does unify with h(W,d). Though is it possible that X = g(Y) since uppercase X looks until it finds a solution?
Yes, it does unify, and it does so because g(Y) is a term to be evaluated, as well as a -- in the first example you pointed.
You can check the evaluation in a prolog interpreter:
?- f(g(Y),h(c,d)) = f(X,h(W,d)).
X = g(Y),
W = c.
The unification process works in a depth-first fashion, unifying members and returning each of the available answer, until no further combination is possible.
This means the unification method is called for f(g(Y),h(c,d)) = f(X,h(W,d)), that finds out the available matchings: g(Y) = X, h(c, d) = h(W, d).
Then, the unification is performed upon g(Y) = X, that, since there's no further possible reduction, returns X = g(Y).
Then, the same method is called upon the matching h(c, d) = h(W, d), which gives you c = W, and no other matching, resulting, thus, in W = c.
The answers, after unification, are returned, and it's usually returned false to point when no matching/further matching is possible.
As pointed by CapelliC, the variable Y, after the unification process, is still unbound. The unification is performed upon unbound variables, which means:
the unification of h(c, d) = h(W, d) returns h(_) = h(_), and this allows the unification to continue, since h is a term, and not an unbound var;
the unification of d = d is a matching of terms, and does not form an attribution -- or binding;
the unification of c = W forms an attribution, and the variable W is bound to the term c, since it was not bound before -- a comparison would be performed otherwise;
the unification of X = g(Y) simply binds the unbound variable X to the term g(Y), and g(Y) is a term with an unbound variable, since there's no available unification to g(Y).
Regards!

Resources