Re: "dict"ionary typing?
Carlo Capelli <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <CABty9wwV+WDbQSeC+4uiws7JKUAakCiMA8+PGc8fnMjYXaK8iQ@mail.gmail.com> |
Thanks, Shon, for your words. Carlo 2013/12/5 Shon Feder <[email protected]> > I believe that what you are describing, Michael, is *exactly* what Carlo > Capelli announced with his `lifter` package, in the "Functional Syntax" > thread yesterday: > > > I crafted my own tiny interface, I'll show it since I got a positive > review > > from an user... > > > > > > > > 1 ?- [lifter]. > > > > % lifter compiled into lifter 0.01 sec, 13 clauses > > > > true. > > > > > > 2 ?- length(List, ° is 1+1). > > > > List = [_G1367, _G1370]. > > > > > > We can name lifted variables, if are worth reuse > > > > > > 3 ?- length(List, °L is 1+1), length(L2, ° is L+2). > > > > List = [_G1740, _G1743], > > > > L = 2, > > > > L2 = [_G1746, _G1749, _G1752, _G1755]. > > I have used the module (https://github.com/CapelliC/prolog-snippets) and I > find it quite interesting. Carlo's approach is interesting for exactly the > reasons you note. > > > I dislike declarations when they can be inferred from usage. I > > particularly dislike function declarations in Prolog because they imply > > that a predicate can only be used as a function in a single "mode". One > might reasonably use append/3 as a function in three different modes. > > > `lifter` implements the same goal_expansion pattern as Richard describes: > > > If a name/arity pair was declared as a function or if > > there was a :- func [mod:]name/arity declaration, then > > in a clause body > > p(...,name(T1,...,Tn),...) > > => > > name(T1, ..., Tn, T0), > > p(..., T0, ...) > > With `lifter`, the clause > > longer(A,B) :- > length(A,º) > length(B,º). > > is expanded to > > longer(A, B) :- > length(A, C), > length(B, D), > C > D. > > I like that this approach satisfies the desire for expressions that > "evaluate in place" but keeps the flexibility and potent, multi-directional > functionality of prolog relations. Also, as with Richards, Playing with > Carlo's module has had me thinking about different ways of understanding a > function within the scope of my limited knowledge of Prolog, maths, and > logic generally. (I apologize, by the way, if the following is too naive to > contribute meaningfully to this discussion). > > Insofar as functions are just ordered pairs of elements belonging to > certain domains, that is, insofar as they are thought of extensionally the > common representation, f(n1, ..., nm), expresses the ordering by omitting a > reference to the right-most element. This is a differently emphasized > articulation of the same relationship that Sterling and Shapiro describe in > 'The Art of Prolog': "The predicate ackermann(M,N,A) denotes that A = > ackerman(M,N)." The predicate describes a function by using the rightmost > argument place to connote the *output*. According to this view, it seems > like `ackermann/3` is thought of as describing a special case of equality. > It might be written more clearly as `equals(ackermann(M,N), A)`. > > The function is governed by equality (which is, in one sense, just a > relation of substitutability: "If one substitutes equals for equals, > equality remains" [^1]). The function can evaluate to its output and > doesn't need to make reference to the ouput element, so we can write y = > f(x) + 2. Of course, in Prolog, we could add to our program the fact > `ackermann(_,_,1).`, and then we're not describing a mathematical function > any more, since every set of inputs returns 1 as well as it's "proper" > value. Because of the important differences between the usual > representation of functions and the common meanings of Prolog predicates, I > am inclined to towards Michael's view on function declarations in Prolog. I > am certain, however, that I'd like any implementation of functions to give > clear syntactic cues of what is going to be substituted for an implicit > value. > > 'lifter' does an excellent job of addressing these issues. I was trying to > find a way of thinking about what 'lifter' does with `º` that made sense to > me, and I kept coming back to the idea of the relative pronoun: it lets us > string dependent clauses together without re-designating the subject each > time. Here's my sloppy translation of a sloppy definition of factorial > written with lifter: > > factorial(0,1). > factorial(N,Fac) :- Fac is factorial(º is (ºN > 0) - 1, º) * N . > > The factorial of N is Fac, if Fac is the factorial of a number N, > which, greater than zero, is subtracted by 1, that is multiplied by N . > > My analogy with relative clauses might not be completely sound, but I do > think the complexity of, and easily convoluted nature of this kind of > pattern of expression is apparent (granted, this is a straw example). > > In any case, I really like what `lifter` suggests about the relationship > between Prolog predicates and functions: the latter is a kind of > proposition is which one argument is emphasized to the point of eclipsing > the others. In fact, however, the function merely hides its extra arguments > and clauses within the internalized conventions of mathematical discourse. > There's a sort of goal expansion going on in our normal use of functions, > and by adopting a some slightly unusual syntax, we can interact with > structure of the expansion procedure in interesting ways (the difference > between Richard's and Carlo's use of goal_expansion). > > I believe that it is in relation to dynamics of this sort that Russell > described functions in preceding sense to be a special case of > *propositional functions*: > > > ... "the father of x" is just as legitimately a function of which x is the > argument as is "the logarithm of X." Functions in this sense are > *descriptive* functions. As we shall see later, there are functions of a > still more general and more fundamental sort, namely, *propositional* > functions; but for the present we shall confine our attention to > descriptive functions, *i.e.* "the term having the relation R to x," or, > for short, "the R of x" ... > > I suspect that Carlo's `º` means most accurately "the term having the > relation ... to ...". It says that the predicate in which it occurs is > really about this one particular thing, such that you can just replace the > predicate in this context with the thing. I think a little more sugar could > maybe be sprinkled onto the `lifter` with good results. For instance, I'd > like to see it implemented through `term_expansion/2` so that it can lift > variables from the head of a clause as well--it could be used to visually > organize conditions on the arguments. Also, I find it awkward to use > arithmetical propositions in this way: e.g. plus(1, º is 4 * 5, X). It > might be interesting to try adding another pattern like º{<Expression>}. > These two additions would let factorial be written like, > > factorial(0, 1). > factorial(ºN > 0, Fac) :- Fac is factorial( º{N - 1}, º) * N > > Actually, I think you could write the second clause thus > > factorial(ºN > 0, º{ factorial( º{N - 1}, º) * N) }). > > In any case, thinking about a function as a description, as Russell > suggests, it becomes quite evident what we would want descriptive functions > for in our language, since they perform the very same service as definite > descriptions of natural language: to express complex relations amongst > objects without needing relative clauses or redundant expression: I can say > > "the father of my friend knows the ceo of the world's richest > corporation" > > rather then > > "father(Father,Friend), friend(Me,Friend), knows(Father, CEO), ceo(CEO, > Corp), largest_in(world, Corporation)." > > I have experimented with using the '.' in atoms to designate a suffix > which, when appended to predicates, replaces the predicate with the > variable in its hidden last argument. This is pretty much the same as > Ciao's tilde operator, I think, only it might look a bit nicer and > contribute to more expressive statements: > > longer(A, B) :- > length.of(A) > length.of(B). > > > In this case, `.of` is simply a suffix that says a term is expanded to be > replaced by the value of it's third argument. The suffixed preposition says > something is being described. So `reverse/2` can be called `reverse.of(L)`. > You don't need a function declaration for these, because they are just > normal predicates hiding their third argument. However, it is sometimes > desirable to have a visual cue as to which predicates are likely to called > on as descriptions, so a simple operator for making the distinction might > be in order: > > v(Expression) => Value :- Value is Expression. > > Where `v` stands for "value" and `=>` is just sugar for expression's sake: > `?- listing(v). v(A, B) :- B is A.` > > ?- X = v.of(length.of([1,2,3,4,5])) * 5 . > > This seems to fit well with the syntax for maps/dics. This could be used in > conjunction with lifter, perhaps? > > factorial(0,1). > factorial(ºN > 0) => factorial.of(º{N - 1}) * N. > > (Which should expand into a totally vanilla Prolog clause). > > Perhaps there could also be a simple, dynamic, multi-file predicate for > adding in new suffixes for kicks: > > descriptive_suffix(.to). > appended(A, B) => C :- append(A,B,C). > > ?- X = appended.to([1,2], [3,4]). > X = [1,2,3,4]. > > --- > > In any case, I have really enjoyed reading these discussions recently and > I'm excited about the developments in swi7, not because I have enough > knowledge to have an opinion on how things should develop, but because I > have benefited greatly from -- and invigorated by -- the discussions that > have emerged in the process. > > I'm sorry this is so long. > > > */ > -------------- next part -------------- > HTML attachment scrubbed and removed > _______________________________________________ > SWI-Prolog mailing list > [email protected] > https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog > -------------- next part -------------- HTML attachment scrubbed and removed