Skip to content

Instantly share code, notes, and snippets.

@lukehoban
Created February 25, 2020 06:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukehoban/0ec2a3dbbb9a13338d338a3fbbb039ff to your computer and use it in GitHub Desktop.
Save lukehoban/0ec2a3dbbb9a13338d338a3fbbb039ff to your computer and use it in GitHub Desktop.
Untyped Lambda Calculus, Chruch Numerals, Y Combinator in Golang
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
type V func(v V) V
var Y V = func(f V) V {
return (func(x V) V { return func(n V) V { return f(x(x))(n) } })(func(x V) V { return func(n V) V { return f(x(x))(n) } })
}
var tru V = func(x V) V { return func(y V) V { return x } }
var fals V = func(x V) V { return func(y V) V { return y } }
var zero V = func(f V) V { return func(x V) V { return x } }
var one V = func(f V) V { return func(x V) V { return f(x) } }
var two V = func(f V) V { return func(x V) V { return f(f(x)) } }
var plus V = func(m V) V {
return func(n V) V { return func(f V) V { return func(x V) V { return m(f)(n(f)(x)) } } }
}
var mult V = func(m V) V { return func(n V) V { return func(f V) V { return func(x V) V { return m(n(f))(x) } } } }
var pred V = func(n V) V {
return func(f V) V {
return func(x V) V {
return n(func(g V) V { return func(h V) V { return h(g(f)) } })(func(u V) V { return x })(func(u V) V { return u })
}
}
}
var isZero V = func(n V) V { return n(func(_ V) V { return fals })(tru) }
var fact V = Y(func(f V) V {
return func(n V) V {
return isZero(n)(func(x V) V { return one })(func(x V) V { return (mult(n)(f(pred(n)))) })(zero)
}
})
var fib V = Y(func(f V) V {
return func(n V) V {
return isZero(pred(n))(func(_ V) V { return n })(func(_ V) V { return plus(f(pred(n)))(f(pred(pred(n)))) })(zero)
}
})
func (f V) toInt() int {
n := 0
f(func(v V) V { n++; return v })(func(v V) V { return v })
return n
}
func (f V) toBool() bool {
var res bool
f(func(v V) V { res = true; return v })(func(v V) V { res = false; return v })(func(v V) V { return v })
return res
}
func Test(t *testing.T) {
three := plus(two)(one)
six := mult(two)(three)
sevenTwenty := fact(six)
eight := fib(six)
assert.Equal(t, 3, three.toInt())
assert.Equal(t, 6, six.toInt())
assert.Equal(t, true, isZero(zero).toBool())
assert.Equal(t, false, isZero(one).toBool())
assert.Equal(t, 720, sevenTwenty.toInt())
assert.Equal(t, 2, pred(three).toInt())
assert.Equal(t, false, isZero(pred(two)).toBool())
assert.Equal(t, 8, eight.toInt())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment