不同数据构造函数的函数

时间:2012-02-04 17:34:10

标签: haskell

我一周前开始学习Haskell并且有一个奇怪的问题。我创建了一个简单的数据类型,并希望在控制台中显示它。我为我的类型的2个构造函数创建了2个函数。如果我使用带有2个参数的构造函数,编译器可以调用函数。但它不能调用另一个应该捕获带有1个参数的构造函数的函数。

module Main (
    main
) where

data MyContainter a b = FirstVersion a b
                  | SecondVersion a
                  deriving(Show,Eq)

showContainer (FirstVersion a b) = show b
showContainer (SecondVersion a) = show a

--startF = showContainer (FirstVersion 1 2) -- it works
startF = showContainer (SecondVersion 1) -- it doesn't work

main = putStr startF

编译器告诉:

Ambiguous type variable `a0' in the constraint:
  (Show a0) arising from a use of `showMaybe'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: showMaybe (SecondVersion 1)
In an equation for `startF': startF = showMaybe (SecondVersion 1)

为什么会这样说?我直接创建了(SecondVersion 1)并且不理解编译器为什么不调用showContainer(SecondVersion a)。

1 个答案:

答案 0 :(得分:9)

问题是showContainer的类型为:

showContainer :: (Show a, Show b) => MyContainer a b -> String

但是当您通过SecondVersion 1时,它不知道b是什么,因为SecondVersion 1适用于任何类型的b!当您传递FirstVersion时,它可以正常工作,因为FirstVersion同时包含ab,因此对于它们应该是什么,从不存在任何歧义。< / p>

因此,由于编译器无法知道您想要的b,并且无法知道b的选择不会影响showContainer(毕竟,它传递FirstVersion时, 会影响行为,因为它对show类型的值使用b,它会放弃。

这就是错误消息所说的:类型变量a0 1 是不明确的,所以请添加一个类型签名来告诉我它是什么。在这种情况下,它无关紧要,因此您可以将其设置为()

startF = showContainer (SecondVersion 1 :: MyContainer Integer ())

您可能不会经常遇到这样的错误,因为您使用值的上下文通常会强制使用特定的b

1 不幸的是,GHC不是挑选类型变量的最佳选择;如果你给我showContainer显式的显式类型签名,那么它也会在错误消息中使用b