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()) }