Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda calculus in scala

OK, so I'm trying to implement the basics of lambda calculus. Here it goes.

My numbers:

def zero[Z](s: Z => Z)(z: Z): Z = z
def one[Z](s: Z => Z)(z: Z): Z = s(z)
def two[Z](s: Z => Z)(z: Z): Z = s(s(z))

Partially (actually, non) applied version of them is smth like that:

def z[Z]: (Z => Z) => (Z => Z) = zero _

Before I continue I define some types:

type FZ[Z] = Z => Z
type FFZ[Z] = FZ[Z] => FZ[Z]

Fine, succ function goes like (Application order should be exactly like that! I took the definition here):

def succ[Z](w: FFZ[Z])(y: FZ[Z])(x: Z): Z = y((w(y))(x))

And the unapplied version of it gets as scary as:

def s[Z]: FFFZ[Z] = successor _

Beg your pardon, here is the missing types:

type FFFZ[Z] = FFZ[Z] => FFZ[Z]
type FFFFZ[Z] = FFFZ[Z] => FFFZ[Z]

But I'm stuck at the add function. If conformed to types and definition (taken here as well) it goes like

def add[Z](a: FFFFZ[Z])(b: FFZ[Z]): FFZ[Z] =
  (a(s))(b)

But I want a to be a common number of type FFZ[Z].

So -- how can I define addition?

like image 556
Vadim Samokhin Avatar asked Apr 22 '16 18:04

Vadim Samokhin


People also ask

What is lambda calculus in Scala?

In this article we are going to dig deep into what functional programming is really all about, how it came into use and its significance. Lambda calculus is a formal system in mathematical logic to express computations in the form of functions.

What is lambda expression in spark?

Lambda expressions, for simple functions that can be written as an expression. (Lambdas do not support multi-statement functions or statements that do not return a value.) Local def s inside the function calling into Spark, for longer code. Top-level functions in a module.

Is lambda calculus a language?

Lambda calculus (λ-calculus), originally created by Alonzo Church, is the world's smallest programming language. Despite not having numbers, strings, booleans, or any non-function datatype, lambda calculus can be used to represent any Turing Machine!

What is a redex lambda calculus?

A redex, or reducible expression, is a subexpression of a λ expression in which a λ can be applied to an argument. With more than one redex, there is more than one evaluation order. e.g. (+(* 3 4) (* 7 6)). Normal Order Evaluation. Always reduce leftmost redex.


2 Answers

It's totally possible to implement Church numerals in Scala. Here is one such rather straight-forward implementation:

object ChurchNumerals {

  type Succ[Z] = Z => Z
  type ChNum[Z] = Succ[Z] => Z => Z

  def zero[Z]: ChNum[Z] =
    (_: Succ[Z]) => (z: Z) => z

  def succ[Z] (num: ChNum[Z]): ChNum[Z] =
    (s: Succ[Z]) => (z: Z) => s( num(s)(z) )

  // a couple of church constants
  def one[Z] : ChNum[Z] = succ(zero)
  def two[Z] : ChNum[Z] = succ(one)

  // the addition function
  def add[Z] (a: ChNum[Z]) (b: ChNum[Z]) =
    (s: Succ[Z]) => (z: Z) => a(s)( b(s)(z) )

  def four[Z] : ChNum[Z] = add(two)(two)

  // test
  def church_to_int (num: ChNum[Int]): Int =
    num((x: Int) => x + 1)(0)

  def fourInt: Int = church_to_int(four)

  def main(args: Array[String]): Unit = {
    println(s"2 + 2 = ${fourInt}")
  }
}

Compiles and prints:

$ scala church-numerals.scala
2 + 2 = 4

If I were to explain Church numerals from scratch I'd add more commentaries. But taking the context into account, I'm not sure on what to comment in this case. Please feel free to ask and I'll add more explanations.

like image 188
Anton Trunov Avatar answered Sep 20 '22 23:09

Anton Trunov


I have coded Numerals, Booleans and Pairs: https://github.com/pedrofurla/church/blob/master/src/main/scala/Church.scala following Church's style.

One thing I noticed is that using the curried function syntax was much easier than using multiple argument lists. Some of the interesting snippets

type NUM[A] = (A => A) => A => A
def succ  [A]: NUM[A]  =>  NUM[A] = m => n => x => n(m(n)(x))
def zero  [A]: NUM[A] = f => x => x
def one   [A]: NUM[A] = f => x => f(x)
def two   [A]: NUM[A] = f => x => f(f(x))
def three [A]: NUM[A] = f => x => f(f(f(x)))
def plus  [A]: (NUM[A]) => (NUM[A]) => NUM[A] = m => n => f => x => m(f)(n(f)(x))

Now for printing them out (very similar to Antov Trunov's solution):

def nvalues[A] = List(zero[A], one[A], two[A], three[A])

val inc: Int => Int  = _ + 1 
def num: (NUM[Int]) => Int = n => n(inc)(0)
def numStr: (NUM[String]) => String = n => n("f (" + _ + ") ")("z")

Some output:

scala> println(nvalues map num)
List(0, 1, 2, 3)

scala> println(nvalues map numStr) // Like this better :)
List(z, f (z) , f (f (z) ) , f (f (f (z) ) ) )
like image 44
pedrofurla Avatar answered Sep 20 '22 23:09

pedrofurla