一周前我开始学习 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)。
最佳答案
问题是 showContainer
具有以下类型:
showContainer :: (Show a, Show b) => MyContainer a b -> String
但是当你通过
SecondVersion 1
,不知道是什么b
是,因为 SecondVersion 1
适用于任何类型的 b
!当您通过 FirstVersion
,它工作正常,因为,如 FirstVersion
包含两个 a
和 b
,对于它们应该是什么,从来没有任何歧义。因此,由于编译器无法知道
b
你想要的,而且无从得知b
的选择不影响 showContainer
(毕竟,它确实会影响您传递 FirstVersion
时的行为,因为它使用 show
类型的值 b
),它放弃了。这就是错误消息的含义:类型变量
a0
1 是模棱两可的,所以请添加一个类型签名来告诉我它是什么。在这种情况下,它是什么并不重要,因此您可以将其设置为 ()
:startF = showContainer (SecondVersion 1 :: MyContainer Integer ())
您可能不会经常遇到这样的错误,因为您使用这些值的上下文通常会强制使用特定的
b
要使用的。1 不幸的是,GHC 在选择类型变量方面并不是最好的;如果你给
showContainer
像我展示的那样显式类型签名,然后它会使用 b
在错误消息中。
关于haskell - 不同数据构造函数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9142863/