“ succ(zero)”的类型与GHC中的“ one”的类型不同

时间:2019-02-13 07:14:10

标签: haskell types type-inference lambda-calculus

要求GHC打印“一”和“ succ零”(编码数字的lambda微积分方式)的类型,我得到两种不同的类型! 他们不应该一样吗? 您还能告诉我如何手动导出其类型吗?

zero = \ f x -> x
one = \ f x -> f x
succ = \ n f x -> f (n (f x))

:t one -- (t1 -> t2) -> t1 -> t2

:t succ zero -- ((t1 -> t1) -> t2) -> (t1 -> t1) -> t2

2 个答案:

答案 0 :(得分:4)

正如评论中所说,正确的定义是

zero   f x = x
succ n f x = f (n f x)
  

“从f开始,在n的{​​{1}}应用后再进行一次f。”

因此

x

最初得到的类型更普遍,

one f x = succ zero f x = f (zero f x) = f x
two f x = succ one  f x = f (one  f x) = f (f x)

但这并不重要,它们之间都相互匹配(统一),并且从zero :: t -> t1 -> t1 -- most general one :: (t1 -> t ) -> t1 -> t -- less general succ one :: (t2 -> t2) -> t2 -> t2 -- most specific 开始,类型便确定为最具体的two = succ one

您也可以定义

(b -> b) -> (b -> b)

且所有类型都与

完全相同
church :: Int -> (b -> b) -> b -> b           -- is derived so by GHCi
church n f x = foldr ($) x (replicate n f)
             = foldr (.) id (replicate n f) x
{- church n  = foldr (.) id . replicate n     -- (^ n) for functions -}

这没关系。

关于类型派生,归结为仅使用了模式/应用规则

church 0 :: (b -> b) -> b -> b
church 1 :: (b -> b) -> b -> b
church 2 :: (b -> b) -> b -> b

只需小心地一致地重命名每种类型,以便在任何步骤都不会引入类型变量:

       f   :: a -> b
         x :: a
       -------------
       f x ::      b

(因为 succ n f x = f (n f x) x :: a f :: t , t ~ ... n :: t -> a -> b f :: b -> c , t ~ b -> c succ n f x :: c succ :: (t -> a -> b) -> (b -> c) -> a -> c :: ((b -> c) -> a -> b) -> (b -> c) -> a -> c 产生的最终结果类型与succ产生的最终结果类型相同-即f),或者按照GHCi的说法,

c

答案 1 :(得分:2)

首先,您希望zeroone具有相同的类型。在zero的等式中,不要在f的rhs上使用->。因此,编译器不知道要推断的类型。在one的方程式中,您希望f x(其结果)与xzero的结果)具有相同的类型。但是你也没有得到。给出签名最简单,但是如果失败,则使用asTypeOf

succ的方程式中,您希望其结果与f x相同,并且与x相同。

  

您还可以教我如何手动导出其类型吗?

好的,让我们使用asTypeOf完成以上操作。然后,您可以使用:t查找类型...

zero = \   f x -> (x `asTypeOf` f x)
one  = \   f x -> (f x `asTypeOf` x)
succ = \ n f x -> (f (n f x)
                 `asTypeOf` f x `asTypeOf` x)

(每个@LambdaFairy我已经为succ使用了正确的定义。)

请注意,教堂数字被用无类型的lambda演算框起来-这就是维基百科所显示的内容。当您了解更多关于它们的奇异函数(例如加法或前代)时,您会发现Haskell是类型化的lambda演算,而GHC会阻碍/您将达到可怕的单态性限制。然后asTypeOf无法帮助您;您必须使用(高级)类型签名。