不同数据构造函数的函数

Ale*_*xey 7 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
Run Code Online (Sandbox Code Playgroud)

编译器告诉:

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)
Run Code Online (Sandbox Code Playgroud)

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

ehi*_*ird 9

问题是showContainer有类型:

showContainer :: (Show a, Show b) => MyContainer a b -> String
Run Code Online (Sandbox Code Playgroud)

但是当你通过时SecondVersion 1,它不知道是什么b,因为SecondVersion 1适用于任何类型的b!当你传递一个时FirstVersion,它工作得很好,因为,FirstVersion既包含a a和a b,它们应该是什么,从来没有任何歧义.

所以,既然编译器无法知道b你想要什么,也无法知道选择b不会影响showContainer(毕竟,当你传递时它影响行为FirstVersion,因为它使用show的是类型的值b),它放弃了.

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

startF = showContainer (SecondVersion 1 :: MyContainer Integer ())
Run Code Online (Sandbox Code Playgroud)

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

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