Haskell中教会编码的布尔的xor

时间:2016-11-23 04:05:51

标签: haskell lambda xor

我目前正在尝试为xor实现lambda表达式。但是,我觉得我错过了一些东西,因为我从bxor表达式中得到了错误。我做错了什么?

true  = \t f -> t    -- always pick the first argument
false = \t f -> f    -- always pick the second argument

toBool = \b -> b True False

bnot = \b -> b true false

bxor = \b x -> b (bnot x) x

1 个答案:

答案 0 :(得分:5)

在打字环境中,需要小心。你的lambda术语在无类型设置中工作正常,但需要在键入的设置中进行一些调整。

我们需要为Church booleans定义一个类型。让我们选择以下参数单态类型。

type B a = a -> a -> a

然后,让我们添加类型注释以检查错误:

true :: B a
true  = \t f -> t

false :: B a
false = \t f -> f

toBool :: B Bool -> Bool
toBool = \b -> b True False

到目前为止,这么好。但是:

bnot :: B a -> B a
bnot = \b -> b false true

会产生类型错误,例如false的类型为B a,而不是a,因此应用b false的类型不合适。我们可以通过添加几个a参数x y来解决这个问题,并相应地简化函数。

bnot = \b x y -> b (false x y) (true x y)
-- or, more simply:
bnot = \b x y -> b y x
-- or even
bnot = flip

此类型检查。同样,我们可以返工bxor进行类型检查:

bxor :: B a -> B a -> B a       
bxor = \b1 b2 x y -> b1 (bnot b2 x y) (b2 x y)

或者,使用布隆的 impredicative Church编码,除了添加相关类型签名外,我们可以使原始代码按原样进行检查。这需要更高级别的类型。

{-# LANGUAGE Rank2Types #-}

type BI = forall a. a -> a -> a

trueI :: BI
trueI = true

falseI :: BI
falseI = false

toBoolI :: BI -> Bool
toBoolI = \b -> b True False

bnotI :: BI -> BI
bnotI = \b -> b falseI trueI

bxorI :: BI -> BI -> BI
bxorI = \b x -> b (bnotI x) x