Scala 中的 lambda 演算
lambda calculus in scala
好的,所以我正在尝试实施 basics of lambda calculus。开始了。
我的号码:
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))
它们的部分(实际上,非)应用版本是这样的:
def z[Z]: (Z => Z) => (Z => Z) = zero _
在我继续之前我定义了一些类型:
type FZ[Z] = Z => Z
type FFZ[Z] = FZ[Z] => FZ[Z]
好吧,succ
函数是这样的(应用顺序应该是正好那样!我接受了定义here):
def succ[Z](w: FFZ[Z])(y: FZ[Z])(x: Z): Z = y((w(y))(x))
它的未应用版本变得如此可怕:
def s[Z]: FFFZ[Z] = successor _
不好意思,这里是缺少的类型:
type FFFZ[Z] = FFZ[Z] => FFZ[Z]
type FFFFZ[Z] = FFFZ[Z] => FFFZ[Z]
但我卡在了 add
函数上。如果符合类型和定义(也采用 here),它就像
def add[Z](a: FFFFZ[Z])(b: FFZ[Z]): FFZ[Z] =
(a(s))(b)
但我希望a
是FFZ[Z]
类型的普通数字。
那么 -- 我如何定义加法?
在 Scala 中实现教堂数字是完全可能的。这是一个相当直接的实现:
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}")
}
}
编译并打印:
$ scala church-numerals.scala
2 + 2 = 4
如果我要从头开始解释教会数字,我会添加更多评论。但考虑到上下文,我不确定在这种情况下该评论什么。请随时提问,我会添加更多解释。
我按照 Church 的风格编写了数字、布尔值和对:https://github.com/pedrofurla/church/blob/master/src/main/scala/Church.scala。
我注意到的一件事是,使用柯里化函数语法比使用多个参数列表要容易得多。一些有趣的片段
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))
现在打印出来(与 Antov Trunov 的解决方案非常相似):
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")
一些输出:
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) ) ) )
好的,所以我正在尝试实施 basics of lambda calculus。开始了。
我的号码:
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))
它们的部分(实际上,非)应用版本是这样的:
def z[Z]: (Z => Z) => (Z => Z) = zero _
在我继续之前我定义了一些类型:
type FZ[Z] = Z => Z
type FFZ[Z] = FZ[Z] => FZ[Z]
好吧,succ
函数是这样的(应用顺序应该是正好那样!我接受了定义here):
def succ[Z](w: FFZ[Z])(y: FZ[Z])(x: Z): Z = y((w(y))(x))
它的未应用版本变得如此可怕:
def s[Z]: FFFZ[Z] = successor _
不好意思,这里是缺少的类型:
type FFFZ[Z] = FFZ[Z] => FFZ[Z]
type FFFFZ[Z] = FFFZ[Z] => FFFZ[Z]
但我卡在了 add
函数上。如果符合类型和定义(也采用 here),它就像
def add[Z](a: FFFFZ[Z])(b: FFZ[Z]): FFZ[Z] =
(a(s))(b)
但我希望a
是FFZ[Z]
类型的普通数字。
那么 -- 我如何定义加法?
在 Scala 中实现教堂数字是完全可能的。这是一个相当直接的实现:
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}")
}
}
编译并打印:
$ scala church-numerals.scala
2 + 2 = 4
如果我要从头开始解释教会数字,我会添加更多评论。但考虑到上下文,我不确定在这种情况下该评论什么。请随时提问,我会添加更多解释。
我按照 Church 的风格编写了数字、布尔值和对:https://github.com/pedrofurla/church/blob/master/src/main/scala/Church.scala。
我注意到的一件事是,使用柯里化函数语法比使用多个参数列表要容易得多。一些有趣的片段
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))
现在打印出来(与 Antov Trunov 的解决方案非常相似):
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")
一些输出:
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) ) ) )