Saturday, June 09, 2007

The Church Code

You may have heard of the lambda calculus, in which everything is a function. And you may have asked yourself, as I have, ok that's great, but I how do I do anything with just functions? How do I create all those datastructures I've become acustommed to? Do I need to build the datastructures I've become accustomed to? If so, how do I do it?

One answer to this question, is the Church encoding, named after Alonzo Church who first came up with the idea. So how do you use Church encoding?

Well, before I get into that I'm going to describe the environment I'm going to use. I'm going to use the ruby programming language, because it's familar to me, and Haskell's type system makes it difficult to use Church encoding. Secondly I'm gonna define a convience method in ruby called curry:


def curry(&l)
lambda { |a| lambda { |b| l[a,b] } }
end


curry takes a block of two arguments and transforms it into a Proc w/ a single argument that returns another Proc of a single argument. This is just to save me typing later.

Now that that's out of the way we can start talking about how to turn our functions into values. Consider one of the simplest values in most programming languages, true and false.


# we are going to use the names ctrue and cfalse because
# ruby takes exception to our using true and false
# as variables
ctrue = curry { |a,b| a }
cfalse = curry { |a,b| b }

Now if you didn't stop reading a while ago because you already know all about this stuff, you may be wondering, how are those functions true and false? Actually, let's just make sure that curry method makes sense first.


curry { |a,b| a } -->
lambda { |a| lambda { |b| a } }
# So to call ctrue we'd do the following:
ctrue[1][0] #=> 1

The reason for currying all these functions should become clear fairly soon. Now that that's out of the way, how does this give us true and false? Well, think about an if statement. Now imagine if was defined as a function, like the following:

cif = lambda { |condition| curry { |true_branch, false_branch|
condition[true_branch][false_branch] } }


Now we can for instance write not:

cnot = lambda { |cond| cif[cond][cfalse][ctrue] }


Now if you've picked up on what's going on with cif you've realized that it's not really necessary. ctrue and cfalse are true and false, and they are also if.

So we can write cnot as

cnot = lambda { |cond| cond[cfalse][ctrue] }

And if we cheat for a moment, we can discover which value a given church encoded boolean is by using the following function

cbool_to_rbool = lambda { |cond| cond[true][false] }


Now we can make sure our cnot method works

>> cbool_to_rbool[ctrue]
=> true
>> not_ctrue = cnot[ctrue]
=> #<Proc:0x02b9876c@(irb):1>
>> cbool_to_rbool[not_ctrue]
=> false

So now what? We've managed to come up with bools out of functions. Doesn't seem very useful yet, although maybe kind of entertaining.

Well we can now also define and and or. A and B is true if A is true and B is true. Put another way, A and B is true if neither A nor B are false.


cand = curry { |a,b| a[b][a] }

So let's walk through this function
if a is true, it will take a the left value and give us b. If b is true, we have true and true -> true, which is what we wanted. if b is false, we have true and false -> false which is again, what we wanted. If a is false, we get a so we had false and anything -> false, which is what we want as well.

Next we can define or.


cor = curry { |a,b| a[a][b] }

If is a true, we get a, if a is false we get b. Therefore we will only get a false result if both a and b are false. Now that we have and, or and not, we can build boolean operation (xor, etc.), and we've done it using only functions. No datastructures in sight.

The next thing we are going to try, is to create some datastructures out of pure functions. The first thing we will create is a pair, that is a list of two values.


cpair = curry { |a,b| lambda { |f| f[a][b] } }
cfst = lambda { |apair| apair[ctrue] }
csnd = lambda { |apair| apair[cfalse] }

cpair is a 3 argument function, it takes the first value for the pair, the second value for the pair, and a function that takes two arguments to use the pair.cfst will let us extract the first value from a pair, and csnd will allow us to extract the second value from a pair. Let's try it out:


>> pair_of_values = cpair["Ok"][5]
=> #<Proc:0x02b7ec40@(irb):12>
>> csnd[pair_of_values]
=> 5
>> cfst[pair_of_values]
=> "Ok"

Now you can see the purpose of using curried functions. It makes it easier for us to partially apply our functions so we can perform multiple operations with an argument of true, selecting the first value. You can also see that we can if we want create tuples of any arity. Since we already have true and false, one way to encode numbers could be to have an N-tuple of bits (true and false) and define the arithmetic operators in terms of logical operations on bits, like the way the ALU of a processor works. An interesting idea, but this is not how Church actually defined numbers with functions.

Instead, he represented natural numbers as the nth composition of a function with itself:


zero = curry { |f, x| x }
one = curry { |f,x| f[x] }
two = curry { |f,x| f[f[x]] }

Writing this definitions can be a bit tedius, so we can define a successor function:

succ = lambda { |n| curry { |f,x| f[n[f][x]] } }
three = succ[two]
four = succ[three]
.
.
.

We also define a function to convert our church numerals to ruby integers so we can see what's going on:

cnum_to_rnum = lambda { |n| n[lambda { |x| x + 1 }][0] }

>> cnum_to_rnum[two]
=> 2

What's happening is that n is composing the function lambda { |x| x + 1 } n times, so in the case of two, it is twice. We then feed it an initial value of zero, so 0 + 1 + 1 = 2.

We can also add our church numerals


plus = curry { |m,n| curry { |f,x| m[f][n[f][x]] } }

>> cnum_to_rnum[plus[two][four]]
=> 6

We can also define multiplication, a predecessor function etc. But I'm getting bored of church numerals so lets move on into how you create algebraic data types. This is going to allow us to create linked lists, trees, pretty much any data structure you can have in a pure functional language.

In Haskell, there is a type Maybe a, (ML has the same type, only they spell it 'a option). The definition in Haskell looks like:


data Maybe a = Just a | Nothing

That is, any value of Maybe Int for instance will either be Nothing or Just some integer value.

We can define this same data structure using just functions. Each constructor, Just and Nothing will be a function. Each value of Maybe a will be a function that takes a function (a -> b) and a value ( b ).


just = lambda { |value| curry { |f,x| f[value] } }
nothing = curry { |f,x| x } # if you recall this is also the definition of cfalse

Haskell also has a type Either a b whose definition looks like:


data Either a b = Left a | Right b

You may have noticed that Maybe a is just a special case of Either a b where we don't care about the second value. Again, we can define this type using only functions. We will have two functions left and right. Both will take a value, and return a function that takes two arguments, two functions, one from a to c and the other from b to c.


left = lambda { |value| curry { |f,g| f[value] } }
right = lambda { |value| curry { |f,g| g[value] } }

Given that an N-tuple can be represented in pairs, and that nested Eithers give us all the sum-types we need we can represent almost any datatype you can define in Haskell (barring things like strictness annotations, FFI, etc.) using pure functions.

For instance, we can define a linked list. In Haskell the definition might look like:


data List a = Cons a (List a) | Empty

Like maybe or either we will have two constructor functions cons, and empty
cons will take two inputs, a head and a tail and return a function taking two functions. The first one will take as parameters the head and the tail, the second will be a value to use if the list is empty. Empty will simple be a function that takes two functions, with the same parameters as the function returned by cons.

cons = curry { |h,t| curry { |cf, ev| cf[h][t] } }
empty = curry { |cf, ev| ev }

Now we can write first and rest to get the first item of the list
and the rest of the list:


first = lambda { |alist| alist[ctrue][nil] }
rest = lambda { |alist| alist[cfalse][nil] }

>> list = cons[1][cons[2][empty]]
=> #
>> h = first[list]
=> 1
>> t = rest[list]
=> #
>> first[t]
=> 2

We can also write the function map for instance:


map = curry { |f,l| l[curry { |h,t| cons[f[h]][map[f][t]] }][empty] }

>> l2 = cons[1][cons[2][cons[3][empty]]]
=> #<Proc:0x00002b1909def588@(irb):10>
>> l3 = map[lambda { |x| x.to_s }][l2]
=> #<Proc:0x00002b1909def588@(irb):10>
>> first[l3]
=> "1"
>> first[rest[l3]]
=> "2"
>> first[rest[rest[l3]]]
=> "3"

Given that we've defined church numerals earlier we can of course use them instead of
ruby numbers. Strings can be represented as lists of characters, and characters as integers, which again can be represented using church numerals. Basically, all you need are functions. I hope you've learned something, or were at least mildly entertained.

28 comments:

Anonymous said...

Very clever. Its cool to see something so abstract implemented in a familiar language like Ruby. Future students of the lambda calculus thank you!

Anonymous said...

A week or so ago, there was a Ruby Quiz solution to the FizzBuzz problem using Church encodings for everything.

Logan Capaldo said...

I seem to be forever just behind Mentalguy. I hadn't seen that, thanks.

Dextra said...

Good for people to know.

Anonymous said...

Уникальная система постоянного роста прибыли!
Такой шанс нельзя упускать!!!
Все подробности здесь: [b]http://www.wix.com/mmm20ll/20[/b]
Почта для связи: [b]mmm20ll@yahoo.com[/b]

Anonymous said...

Just happened to see this after ~5 years ;-) .. but shouldn't it be

cons = curry { |h,t| curry { |cf, ev| cf[h][t[cf][ev]] } }

because the tail is a list, so it wants an operation and an initial value?

Anonymous said...

wow server http://warlife.ru и нижегородское кольцо http://nn-fun.ru вместе http://0we.ru и онлайн http://orange31.ru а так же с сервером http://wow-nsk.ru и городским порталом http://ipsinnovation.com представляют http://05o.ru обо хостинг http://0vv0.ru и нижегородской области http://berkat.su q http://maksima.su wowqrsk http://aquarellse.su и wowpso http://pso-wow.com славики http://slavich.su twilight http://wow-twilight.ru lord wc3 http://a-sa.su кавказцы http://wolike.ru wow wolike http://shift-wow.ru shift deathwing-rage.ru server gigant-online.ru Centralniy city http://teldrassil.ru gm сервер http://bg-ski.ru лыжи в богородске http://qwest.su
[url=http://nn-fun.ru]1[/url] [url=http://warlife.ru]2[/url] [url=http://ipsinnovation.com] 3[/url] [url=http://orange31.ru]4[/url] [url=http://0we.ru]5[/url] [url=http://05o.ru]6[/url] [url=http://wow-nsk.ru]8[/url] [url=http://1eurobank.com]9[/url]

Anonymous said...

Интернет магазин ShopForYou.org это оригинальные товары для мужчин и женщин по доступным ценам!
У нас можно встретить большой выбор парфюмерии.

Anonymous said...

Рекомендую прикольный портал [url=http://obzormania.ru/igronevs/96-novyy-apdeyt-k-lord-of-the-rings-online.html]Новый апдейт к Lord of the Rings Online[/url] , даже про [url=http://obzormania.ru/igronevs/90-gta-v-dostupna-dlya-predvaritelnogo-zakaza.html]GTA V доступна, для предварительного заказа[/url] есть информация.

Anonymous said...

Настоятельно новый портал [url=http://obzormania.ru/igronevs/64-i-snova-novyy-treyler-k-ssx.html]И снова новый трейлер к SSX[/url] , даже про [url=http://obzormania.ru/igronevs/90-gta-v-dostupna-dlya-predvaritelnogo-zakaza.html]GTA V доступна, для предварительного заказа[/url] очень интересно написано.

Anonymous said...

Рекомендую улётный сайт [url=http://obzormania.ru/obzor/132-forsaken-world.html]Forsaken World[/url] , даже про [url=http://obzormania.ru/igronevs/115-podoshla-pora-i-black-ops-2-raskryt-vse-sekrety.html]В сеть просочилась новая информация об игре Black Ops 2[/url] очень интересно написано.

Anonymous said...

У нас самые лучшие девочки по вызову, индивидуалки, есть с подружкой [url=http://123prost.ru]Проститутки Москвы и других городов[/url],[url=http://m123yandex.ru] девочки повызову, вызвать девочку к себе, проститутки по станциям метро[/url] ,[url=http://stopru.ru]девочки по вызову[/url],[url=http://stopru.ru] Шлюхи здесь, шалуньи[/url], [url=http://3d-net.ru]Заказ девочек-проституток, Форум проститутки москвы[/url],[url=http://deskru.ru] Как купить или продать фото, работа в микростоках[/url]

Anonymous said...

Привет всем, есть вопрос, попался сайт [url=http://kladidengu.clan.su/]kladidengu.clan.su[/url] kladidengu.clan.su, не могу разобраться как тут зарабатывают, кто нибудь может пояснить? Заранее спасибо.

Anonymous said...

У нас самые лучшие девочки по вызову, индивидуалки, есть с подружкой
[url=http://123prost.ru]Проститутки Москвы и других городов[/url],
[url=http://m123yandex.ru] девочки повызову, вызвать девочку к себе,
проститутки по станциям метро[/url] ,[url=http://stopru.ru]девочки по вызову[/url],
[url=http://stopru.ru] Шлюхи здесь, шалуньи[/url], [url=http://3d-net.ru]Заказ девочек-проституток,
Форум проститутки москвы[/url],[url=http://deskru.ru]
Как купить или продать фото, работа в микростоках[/url]

Anonymous said...

У нас самые лучшие девочки по вызову, индивидуалки, есть с подружкой
[url=http://123prost.ru]Проститутки Москвы и других городов[/url],
[url=http://m123yandex.ru] девочки повызову, вызвать девочку к себе,
проститутки по станциям метро[/url] ,[url=http://stopru.ru]девочки по вызову[/url],
[url=http://stopru.ru] Шлюхи здесь, шалуньи[/url], [url=http://3d-net.ru]Заказ девочек-проституток,
Форум проститутки москвы[/url],[url=http://deskru.ru]
Как купить или продать фото, работа в микростоках[/url]

Anonymous said...

У нас самые лучшие девочки по вызову, индивидуалки, есть с подружкой
[url=http://123prost.ru]Проститутки Москвы и других городов[/url],
[url=http://m123yandex.ru] девочки повызову, вызвать девочку к себе,
проститутки по станциям метро[/url] ,[url=http://stopru.ru]девочки по вызову[/url],
[url=http://stopru.ru] Шлюхи здесь, шалуньи, проститутки[/url], [url=http://3d-net.ru]Заказ девочек-проституток,
Форум проститутки москвы[/url],[url=http://deskru.ru]
Как купить или продать фото, работа в микростоках[/url],
[url=http://devki.sexyi.am/]Заказать проститутку[/url]
[url=http://wareza-net.ru]девочки по вызову[/url],
[url=http://pr-tutki.ru/]Проститутки Москвы
идругих городов[/url]

Anonymous said...

Сайт [url=http://tvoiamyzika.ru/]аккордов с табами[/url],
у нас очень охрененная подборка гитарных аккордов и песен перед гитару.
Посетив нас вы станете очень рады качеством и удобством нашего сайта с [url=http://tvoiamyzika.ru/lr]аккордами под гитару[/url]

Anonymous said...

В помощь вашему бизнесу:
Самые новые базы данных предприятий России - 73 города,
последнее обновление - октябрь 2012г,
более 200Мб информации, а это более 1,5 млн.контактов.
Адрес, сфера организации, вид деятельности, телефон, факс, сайт, email, долгота/широта, время работы.
Цена - 2000р.
Гарантии - любые.
http://bulletben.biz/
99995791 - ICQ
admin@bulletben.biz - email

Anonymous said...

В помощь вашему бизнесу:
Самые новые базы данных предприятий России - 73 города,
последнее обновление - октябрь 2012г,
более 200Мб информации, а это более 1,5 млн.контактов.
Адрес, сфера организации, вид деятельности, телефон, факс, сайт, email, долгота/широта, время работы.
Цена - 2000р.
Гарантии - любые.
http://bulletben.biz/
99995791 - ICQ
admin@bulletben.biz - email

Anonymous said...

Под ключ Косметический Ремонтик квартир в Запорожье http://ukladka-kafelj.ucoz.ua http://poklejka-oboev.at.ua http://ukladkalaminata.at.ua

Anonymous said...

http://uslugi.bezgazet.zp.ua/zaporozhie/1217974.html http://zaporozhe.era.com.ua/market/id/ukladka-kafelnoykeramicheskoy-plitki-mozaikav-zaporozhe_387261

Anonymous said...

http://zaporozhe.era.com.ua/market/id/remont-kuhni-pod-klyuch-ili-chastichnyy-remont-kuhniv-zaporozhe_411359 http://zaporozhe.era.com.ua/market/id/ukladka-kafelnoykeramicheskoy-plitki-mozaikav-zaporozhe_387261 http://zaporozhe.era.com.ua/market/id/shpaklevkashtukaturkapokraskagruntovka-sten-i-potolkovv-zaporozhe_387265/ http://zaporozhe.era.com.ua/market/id/montazh-gipsokartona-1-2-3-urovnyav-zaporozhe_387263/ http://zaporozhe.era.com.ua/market/id/remont-kvartiry-i-ofisov-v-zaporozhe-pod-klyuch_387256/ http://zaporozhe.era.com.ua/market/id/pokleyka-oboev-lyuboy-slozhnosti-v-nuzhnye-srokiv-zaporozhe_387258/ http://zaporozhe.era.com.ua/market/id/ukladka-laminatakovrolinalinoleumaparketaplintusama-doskiosbstyazhka-pola_387259 http://zp.doskaukr.com.ua/uslugi/stroitelsvo-remont/post?id=111639 http://zp.doskaukr.com.ua/uslugi/stroitelsvo-remont/post?id=111640

Anonymous said...

ВсемСварочные работы в Самаре. Делаем сварочные и монтажные работы по индивидуальным строительным проектам. Сварочные работы в Самаре! Наш сайт [url=http://svarka63.ru/svarochnye-raboty-v-samare/[/url].

Anonymous said...

КаждомуСварочные работы в Самаре. Делаем сварочные и монтажные работы по индивидуальным строительным проектам. Сварочные работы в Самаре! Наш сайт [url=http://xn--63-6kcai3c0bf.xn--p1ai/svarochnye-raboty-v-samare/[/url].

Anonymous said...

ПРОДАМ участок ЧЕЛЯБИНСКАЯ ОБЛАСТЬ МАЛЫЙ КРЕМЕНКУЛЬ, 7СОТОК СОБственость 89080791300 Email: etd09@mail.ru

Anonymous said...

Unknown message

Anonymous said...

Куплю конденсаторы км-5 H30 (зеленые)
от 1 кг! Предложения на мыло
serg12011974@mail.ru

Anonymous said...

[url=http://markizam.ru/]защитные экраны от солнца маркизы[/url]
[url=http://markizam.ru/index.php?route=product/category&path=97]тент для перголы[/url]


Устали от нескончаемого солнца, но при этом не хотите постоянно пребывать в доме? Кроме того, согласитесь, совсем некомфортно, если еще и пойдет дождь,
В наши дни очень большой любовью пользуются так называемые маркизы, которые сможете найти на нашем сайте сайте. Это надежные тенты, которые можно натянуть на улице, а также их устанавливают для дач и загородных коттеджей, ведь их просто натягивать, пользоваться такими маркизами очень удобно. Такие небольшие тенты, размеры которых вы сможете выбирать самостоятельно, защищают не только от самих палящих палящих лучей, но и от их излучения, так что теперь на улице за столиком вам будет очень удобно, прохладно.
Есть только две проблемы, которые заставят его сложить обратно: либо очень сильный ветер, либо шторм.
На нашем ресурсе вы без труда сможете заказать нужный вам товар, стоит просто выбрать маркиз то, что вам подходит, исходя из различных характеристик. Естественно, свои вопросы вы должны задавать и специалистам, которые обязательно помогут подобрать тот продукт, который нужен. Основные преимущества таких товаров в том, что они легко трансформируются, перевозятся и непосредственно устанавливаются в любом нужном месте.

[url=http://markizam.ru/]маркизы для дачи недорого[/url]
[url=http://markizam.ru/korzinnye]маркизы для террас цена[/url]