Haskell 用于不同数据构造函数的函数
我一周前开始学习Haskell,有一个奇怪的问题。我创建了一个简单的数据类型,并希望在控制台中显示它。我为我的类型的2个构造函数创建了2个函数。如果我使用带有2个参数的构造函数,编译器可以调用函数。但是它不能调用另一个函数,该函数应该捕获一个带有1个参数的构造函数Haskell 用于不同数据构造函数的函数,haskell,Haskell,我一周前开始学习Haskell,有一个奇怪的问题。我创建了一个简单的数据类型,并希望在控制台中显示它。我为我的类型的2个构造函数创建了2个函数。如果我使用带有2个参数的构造函数,编译器可以调用函数。但是它不能调用另一个函数,该函数应该捕获一个带有1个参数的构造函数 module Main ( main ) where data MyContainter a b = FirstVersion a b | SecondVersion a
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)。问题在于
showContainer
的类型为:
showContainer :: (Show a, Show b) => MyContainer a b -> String
但是当您通过secondversion1
时,它不知道b
是什么,因为secondversion1
适用于任何类型的b
!当您传递一个FirstVersion
时,它可以正常工作,因为FirstVersion
同时包含a
和b
,所以它们应该是什么,从来没有任何歧义
因此,由于编译器无法知道您想要什么b
,也无法知道b
的选择不会影响showContainer
(毕竟,当您传递FirstVersion
时,它确实会影响行为,因为它对b
类型的值使用show
),它放弃了
这就是错误消息所说的:类型变量a0
1不明确,因此请添加一个类型签名来告诉我它是什么。在这种情况下,它是什么并不重要,因此您可以将其设置为()
:
您可能不会经常遇到这样的错误,因为您在中使用值的上下文通常会强制使用特定的b
不幸的是,GHC在选择类型变量方面不是最好的;如果您给了
showContainer
一个像我所展示的那样的显式类型签名,那么它也会在错误消息中使用b
。这有助于认识到错误消息中的类型变量a0
与b
相同,与a
无关。(编译器恰好选择了这个名称,因为Show
类使用了a
)这个名称。谢谢,这是一个很好的描述)
startF = showContainer (SecondVersion 1 :: MyContainer Integer ())