Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 用于不同数据构造函数的函数_Haskell - Fatal编程技术网

Haskell 用于不同数据构造函数的函数

Haskell 用于不同数据构造函数的函数,haskell,Haskell,我一周前开始学习Haskell,有一个奇怪的问题。我创建了一个简单的数据类型,并希望在控制台中显示它。我为我的类型的2个构造函数创建了2个函数。如果我使用带有2个参数的构造函数,编译器可以调用函数。但是它不能调用另一个函数,该函数应该捕获一个带有1个参数的构造函数 module Main ( main ) where data MyContainter a b = FirstVersion a b | SecondVersion a

我一周前开始学习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
但是当您通过
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 ())