Newsgroups: comp.lang.functional
Date: 29 Aug 2002 18:49:17 -0700
Local: Thurs, Aug 29 2002 9:49 pm
Subject: Symmetric difference in LC, P-numerals, and fold
This article derives a term in the pure untyped lambda-calculus that
_efficiently_ computes a symmetric difference of two Church numerals. We introduce other numerals, so called P-numerals, which are more convenient for arithmetics. We show the connection between the P-numerals and the list fold. Let cn denote a Church numeral corresponding to the natural number To realize the above algorithm more conveniently, let us introduce c0 f x --> x We define P-numerals as follows: p0 f x --> x { the same as c0 } The conversion from Church numerals to P-numerals is trivial: P-numerals represent the "list" we have mentioned earlier. Indeed, In the following, we would be using the lambda-calculator in Haskell First, we load the calculator and the definitions of common lambda terms > import Prelude hiding ((^),succ,not,or,and) We need to make a few variables with mnemonic names: > import Lambda_calc > import LC_basic > [pn,cn,ck,cl,seed] = Now we can define P-numerals > map make_var ["pn","cn","ck","cl","seed"] > p0 = c0 and the conversion functions > succp = pn ^ f ^ x ^ f # pn # (pn # f # x) > p1 = succp # p0 > p2 = succp # p1 > c2p = cn ^ cn # succp # p0 We can test what we've got: "print c2" prints > p2c = pn ^ pn # (pn ^ seed ^ succ # seed) # c0 (\f. (\x. f (f x))) and "print $ eval $ c2p # c2" prints the p2-numeral (\f. (\x. f (\f. f (\f. (\x. x))) (f (\f. (\x. x)) x))) which we can convert back to the Church form print $ eval $ p2c # (c2p # c2) (\f. (\x. f (f x))) Note that "print $ eval $ c2p # p2c" prints "(\f. f)", the identity function. Now we can define the diffs term, by literally following the algorithm > diffs = ck ^ cl ^ toc # (ck # up_or_down # (cons # false # (c2p # cl))) diffs is the genuine Lambda term. We can ask the calculator to print it > where > -- make variables > [arg,ud_flag,prev,dummy] = > map make_var ["arg","ud_flag","prev","_"] > -- curry the argument > up_or_down = arg ^ up_or_down' # (car # arg) # (cdr # arg) > -- if ud_flag is 'true', we build on the pn > -- if ud_flag is false, we shorten pn, unless it is already p0 > -- in the latter case, we switch the flag > -- we return a pair (new_flag,new_pn) > up_or_down' = ud_flag ^ pn ^ > lif # ud_flag > -- the flag was true: build > # (cons # true # (succp # pn)) > -- the flag was false: we're going down > # (pn > -- pn was > p0: shorten > # (prev ^ dummy ^ cons # ud_flag # prev) > -- pn was p0: we will be going up > # (cons # true # (succp # p0))) > -- Convert the resulting (flag,pn) to the Church numeral > toc = arg ^ (p2c # (cdr # arg)) out (literally by _printing_ it): (\ck. (\cl. (\arg. (\pn. pn (\pn. (\seed. (\c. (\f. (\x. f (c f x)))) I submit the "Haskell" format for the term was more comprehensible. Here are a few tests: If we assume the normal or a similar lazy order of evaluation, Let us relate the P-numerals and the list fold. We can choose the 0 -- [] This representation has the remarkable property that for all i>j, foldr f z peano(0) --> z Comparing these equations with the definition of P-numerals above, we which explains the name for P-numerals. We should also note that Dealing with data structures such as [[[[]],[]],[[]],[]] is inconvenient 0 -- [] This format also has the same property that for i>j, repr(j) is a > mfoldr f z [] = z This mfoldr is equivalent to the foldr over the original Peano > mfoldr f z (_:p) = f p (mfoldr f z p) representation. We can write P-numerals as pn = \f z -> mfoldr f z (take n $ repeat []) and the regular Church numerals as cn = \f z -> mfoldr (\_ seed -> f seed) z (take n $ repeat []) You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
| ||||||||||||||