9

我正在尝试使用以下定义在 haskell 中打印教堂数字:

0 := λfx.x
1 := λfx.f x

哈斯克尔代码:

c0 = \f x -> x
c1 = \f x -> f x

当我在 haskell 控制台中输入它时,我收到一条错误消息

    test> c1

    <interactive>:1:0:
    No instance for (Show ((t -> t1) -> t -> t1))
      arising from a use of `print' at <interactive>:1:0-1
    Possible fix:
      add an instance declaration for (Show ((t -> t1) -> t -> t1))
    In a stmt of an interactive GHCi command: print it

我无法准确弄清楚错误的含义。

谢谢!

4

2 回答 2

15

这里的问题是,默认情况下,不可能在 Haskell 中打印值。打印内容的默认方式——由print函数和 GHCi REPL 等使用——是show由类型 class 定义的函数Show

那么,你得到的错误是告诉你你已经评估了一个没有Show定义实例的类型的表达式。模数一些废话,这就是错误消息的全部内容:

No instance for (Show ((t -> t1) -> t -> t1))

该类型((t -> t1) -> t -> t1)是为您评估的表达式推断的。这是 Church 数字 1 的有效类型,但 Church 数字的“正确”类型实际上应该是(a -> a) -> a -> a

  arising from a use of `print' at <interactive>:1:0-1

它隐式使用该print函数来显示值。通常这会告诉你在程序的哪个位置发现了错误,但在这种情况下,它会说<interactive>:1:0-1因为错误是由 REPL 中的表达式引起的。

Possible fix:
  add an instance declaration for (Show ((t -> t1) -> t -> t1))

这只是建议您可以通过定义它所期望的实例来修复错误。


现在,您可能想实际打印您的 Church 数字,而不仅仅是知道为什么不能。不幸的是,这并不像添加它要求的实例那么简单:如果你为 编写一个实例(a -> a) -> a -> a,Haskell 将其解释为任何特定a的实例,而 Church 数字的正确解释是一个多态函数,适用于任何任意a.

换句话说,你希望你的show函数是这样的:

showChurch n = show $ n (+1) 0

如果你真的想要,你可以像这样实现 Show 实例:

instance (Show a, Num a) => Show ((a -> a) -> a -> a) where
    show n = show $ n (+1) 0

并添加{-#LANGUAGE FlexibleInstances#-}到文件的第一行。或者您可以实现类似的东西将它们转换为常规数字

> churchToInt c1
1
> showChurch c1
"1"

等等

于 2011-06-24T02:54:00.043 回答
6

编辑:剧透警报,如评论中所述

或者,您可以使用 Church 数字类型,如下所示:

data Church x = Church ((x -> x) -> x -> x)

zero :: Church x
zero = Church (\f x -> x)

-- Hack to not clash with the standard succ
succ_ :: Church x -> Church x
succ_ (Church n) = Church (\f x -> (f (n f x)))

instance (Num x) => Show (Church x) where
  show (Church f) = show $ f (1 +) 0
于 2011-06-24T06:18:44.483 回答