Ghci错误:Show没有实例

时间:2015-05-15 22:49:49

标签: haskell

这适用于ghci

data MyList a = Empty | Cons a (MyList a) deriving (Show, Eq, Read, Ord)

let x = Cons(21, Cons(12, Empty))

但是当我输入时:

Prelude> x

我收到此错误:

No instance for (Show (MyList (Integer, MyList (Integer, MyList a0) ->
MyList (Integer, MyList a0)) ->
MyList (Integer, MyList (Integer, MyList a0) ->
MyList (Integer, MyList a0)))) arising from a use of `print'

1 个答案:

答案 0 :(得分:8)

您使用错误的语法进行功能应用。以下代码可以满足您的需求:

let x = Cons 21 (Cons 12 Empty)

原因是Cons构造函数是一个curried函数,但你将它视为一个未经验证的函数。

Curried函数

考虑以下函数添加两个整数:

add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)

这里我们说add是一个函数,它接受x类型的参数Int并返回一个函数, 它接受类型y的参数Int并返回x + y类型的Int

我们可以将此功能应用为(add 1) 2评估为3

函数应用程序在Haskell中是左关联,这意味着我们不需要括号 在(add 1) 2中,只需撰写add 1 2

函数类型构造函数->在Haskell中是右关联,这意味着我们不需要add :: Int -> (Int -> Int)中的括号,只需编写{{ 1}}。

此外,我们不必使用lambdas明确定义add :: Int -> Int -> Int,并且可以使用以下表示法:

add

将多参数函数编码为单参数函数返回单参数函数在Haskell中非常常见。这种方法具有很好的属性,我们也可以部分应用一个函数。例如,以下函数只需一个add :: Int -> Int -> Int add x y = x + y 并添加2:

Int

但我们也可以部分应用 add2 :: Int -> Int add2 x = add 2 x 并简单地写:

add

这也称为无点符号,其中参数称为点。

未解决的职能

可以使用元组值来完成多参数函数的替代编码,即

add2 :: Int -> Int
add2 = add 2

我们可以调用此函数,例如add' :: (Int, Int) -> Int add' (x, y) = x + y ,它构造对add' (2, 3)并将其作为单个参数传递给(2, 3) :: (Int, Int)函数。

Uncurried< - >咖喱

在标准库中有两个函数可以在两种样式之间转换函数。

add'

例如curry :: ((a, b) -> c) -> a -> b -> c curry f x y = f (x, y) uncurry :: (a -> b -> c) -> (a, b) -> c uncurry f (x, y) = f x y 为我们提供了curry add'add为我们提供了uncurry add

回到解释ghci的漫步

请注意,我们也可以将未经验证的应用程序编写为add',它与部分应用程序和多态性一起解释了为什么add'(2, 3)不会直接导致错误,但ghci随后说出了神秘的东西关于let x = Cons(21, Cons(12, Empty))的评估。 这里发生的事情是x是某种类型(12, Empty)的{​​{1}}类型对。 然后将该对用作(Int, MyList a)中的第一个参数,因此我们得到一个部分应用的函数 a并将Cons (12, Empty)作为此列表的元素追加。 MyList (Int, MyList a)同样适用于我们部分应用一对21和前面提到的部分函数。最后,我们告诉ghci打印一个无法显示的函数,因此会抱怨相应函数类型缺少(12, Empty)实例。