Haskell基本显示简单递归数据类型的实例不起作用

时间:2016-07-21 09:42:49

标签: haskell

我有一个简单的问题。本规范对我来说非常好。

main = do
      print("10-2")
      let a = L
      let b = E "abc" a
      print(a)
      print(b)


  data List a = L | E a (List a)

  instance (Show a) => Show (List a) where
      show L = "Empty"
      show (E a list) = (show a)++ (show list)

但它会产生以下错误:

10-2.hs:5:5:
    No instance for (Show a0) arising from a use of `print'
    The type variable `a0' is ambiguous...

我无法找到问题所在。谢谢你的帮助!

3 个答案:

答案 0 :(得分:4)

在您的函数main中,当您编写let a = L时,a的类型只是List a0。当编译器试图知道它必须使用哪个版本的Show实例时,所有类型都适合,因为a的类型未完全定义。但是,如果您删除了行print a,则会看到print b将起作用,因为b的类型只能是List String,并且编译器确切地知道哪个版本show它必须使用。

main = do
  print "10-2"
  let a = L
  let b = E "abc" a
  -- print a
  print b

尝试编写print [],您将看到编译器会给您带来同样的错误。

但是,在ghci中,如果只输入print Lprint [],则不会提示错误。我不知道为什么会这样。

答案 1 :(得分:4)

如果你试图编译这个简单的程序,你会得到同样的错误:

main = print []

什么? Haskell无法打印空列表?这是正确的,它不能。也就是说,除非已知列表元素的类型。在这种情况下不知道,因此编译失败。为了了解原因,请运行以下两个程序:

main = print ([] :: [Int])
main = print ([] :: [Char])

输出不同,但这些程序之间的唯一区别是空列表的类型。

然而,如果您在ghci中尝试同样的模糊程序,它会打印[]就好了!

Prelude> let main = print []
Prelude> main
[]
Prelude>

这是因为ghci的{​​{3}}略高于ghc。因此,如果您将数据类型定义加载到ghci并在提示时说print Lghci将很乐意遵守:

[1 of 1] Compiling Main             ( h.hs, interpreted )
Ok, modules loaded: Main.
*Main> print L
Empty
*Main>

答案 2 :(得分:1)

正如其他人已经说过的那样,你需要给你的List一个类型,即使数据构造函数不需要它来创建自己。

所以试试看:

print (L :: List Int) 

或者你喜欢的只是打印你的(列表a)的显示实例的字符串