lambdaprologmeta-predicate

Lambdas in Prolog?


I normally was able to figure out some usages of Lambda with maplist, but in general have hard time using lambda in prolog. It is probably because it differ from other languages, because of unification.

Here is one of the sticking points : How do you apply declared Lambda expression ? f.e.

LAM = \X^R^(....)

(weird, there have to be space between = and \)

how do you do :

\(LAM)(abc,R)

Another thing which I want to do is to store Lambda expression like a FACT, so that I can query it, but also have it like a lambda function so I can do later binding..f.e. just of the top of my head ... i could think it wrong ..

move = \Obj^From^To(move(Obj,From,To))

instantiate :

?- \(move)(ball,ground,table).

or partially :

?- L2 = \(move)(ball).
?- L3 = \(L2)(table,floor)

query :

?- move(ball,F,T).

Solution

  • Let's consider the following lambda term:

    ?- LAM_2 = \X^R^atom_chars(X,R).
       LAM_2 = \X^R^atom_chars(X,R).
    

    The _2 reminds us that two arguments are lacking in order to make this a real goal.

    To use it, you have now to supply these two arguments. Either with some meta-predicate like maplist/3 or with call/3.

    ?- LAM_2 = \X^R^atom_chars(X,R), call(LAM_2, abc, Res).
       LAM_2 = \X^R^atom_chars(X,R), Res = [a,b,c].
    ?- LAM_2 = \X^R^atom_chars(X,R), maplist(LAM_2, [abc,def], Xss).
       LAM_2 = \X^R^atom_chars(X,R), Xss = [[a,b,c],[d,e,f]].
    

    Note that the variables X and R do not get instantiated!

    What is really a bit unusual is that there is no direct scoping of logic variables. They are all global within a clause, so we have to pay attention that these variables are not accidentally reused.

    Also note that we could have written for above example, just:

    ?- LAM_2 = atom_chars, call(LAM_2, abc, Res).
       LAM_2 = atom_chars, Res = [a,b,c].
    

    to store Lambda expression like a FACT, so that I can query it

    Why not define the fact directly? There is no way to do this otherwise.

    The example you give makes sense, provided we have already the fact defined:

    move(ball, table, floor).
    

    Now we can construct the query incrementally by adding arguments by wrapping call/2 around.

    ?- L1_3 = move, L2_2 = call(move, ball), L3_0 = call(L2_2, table, X), L3_0.
       L1_3 = move, L2_2 = call(move, ball),
          L3_0 = call(call(move, ball), table, floor), X = floor.
    

    However, please note that such partial goals are rarely used today. Also the direct usage of call/N is mostly reserved to meta-predicates like maplist/3.