我正在尝试在Scala的lambda演算中实现基本的布尔逻辑,但我始终处于起步阶段。
我有两种类型:
type λ_T[T] = T => T
type λ_λ_T[T] = λ_T[T] => T => T
“ false”效果很好:
def λfalse[T]: λ_λ_T[T] = (s: λ_T[T]) => (z: T) => z
但是当我尝试实现'true'时(如lambda微积分的数学背景中给出的那样),我得到了错误的类型:
def λtrue[T]: λ_λ_T[T] = (s: λ_T[T]) => (z: T) => s
结果错误:类型λ_T[T]的表达与预期的类型T不符
我该如何实现?
答案 0 :(得分:3)
布尔型is of type的教堂编码
[X] => X -> X -> X
其中[X] =>
表示X -> X -> X
部分在X
中是多态的。
这里有两个建议,您可以在Scala中表达这一点。
布尔值作为通用方法,在呼叫站点键入推论
这里是一种适用于布尔值的类型,在布尔值中可以直接在调用站点上推断所需的多态类型参数:
type B[X] = X => X => X
以下是true
和false
的定义,以及一些操作:
def churchTrue[X]: B[X] = a => b => a
def churchFalse[X]: B[X] = a => b => b
def ifThenElse[X](b: B[X], thenResult: X, elseResult: X) =
b(thenResult)(elseResult)
def and[X](a: B[B[X]], b: B[X]): B[X] = a(b)(churchFalse)
def or[X](a: B[B[X]], b: B[X]): B[X] = a(churchTrue)(b)
def not[X](a: B[B[X]]) = a(churchFalse)(churchTrue)
示例:
println("t & t = " + and[String](churchTrue, churchTrue)("t")("f"))
println("t & f = " + and[String](churchTrue, churchFalse)("t")("f"))
println("f & t = " + and[String](churchFalse,churchTrue)("t")("f"))
println("f & f = " + and[String](churchFalse,churchFalse)("t")("f"))
请注意,这不允许您表达“ Church-Boolean per-se”的概念,因为它需要固定类型的参数才能应用(上面示例中的String
)。尝试从一个特定的调用站点提取表达式并将其移到其他位置时,您必须重新调整所有类型参数,这很烦人。
布尔的真正多态教堂编码
如果要将真正的多态函数表示为一类对象,则必须定义特征或抽象类。对于布尔值,这就像
trait B {
def apply[X](trueCase: X, elseCase: X): X
}
请注意,现在apply
方法在X
中是多态的。这使您可以将布尔型的Church编码实现为可传递的一流对象(从方法返回,保存在列表中等):
trait B { self =>
def apply[X](thenCase: X, elseCase: X): X
def |(other: B): B = new B {
def apply[A](t: A, e: A) = self(True, other)(t, e)
}
def &(other: B): B = new B {
def apply[A](t: A, e: A) = self(other, False)(t, e)
}
def unary_~ : B = self(False, True)
}
object True extends B { def apply[X](a: X, b: X) = a }
object False extends B { def apply[X](a: X, b: X) = b }
这里是将其应用于某些实际值的方法:
def toBoolean(b: B): Boolean = b(true, false)
上面的行将调用apply[Boolean](...)
。
一个例子:
println("And: ")
println(toBoolean(True & True))
println(toBoolean(True & False))
println(toBoolean(False & True))
println(toBoolean(False & False))
println("Or:")
println(toBoolean(True | True))
println(toBoolean(True | False))
println(toBoolean(False | True))
println(toBoolean(False | False))
println("Funny expresssion that should be `true`:")
println(toBoolean((False | True) & (True & ~False)))
打印:
And:
true
false
false
false
Or:
true
true
true
false
Funny expresssion that should be `true`:
true