Haskell 使用typeclass实例时自动识别类型?

Haskell 使用typeclass实例时自动识别类型?,haskell,typeclass,Haskell,Typeclass,我将介绍一些基本的typeclass实现: data Colour = Red | Green | Black class BasicEquality a where isEqual :: a -> a -> Bool instance BasicEquality Bool where isEqual True True = True isEqual False True = True isEqual True False = True isE

我将介绍一些基本的typeclass实现:

data Colour = Red | Green | Black

class BasicEquality a where
   isEqual :: a -> a -> Bool

instance BasicEquality Bool where
  isEqual True True    = True
  isEqual False True   = True
  isEqual True False   = True
  isEqual _ _          = False

instance BasicEquality Colour where
  isEqual Red Green    = True
  isEqual _ _          = False

instance BasicEquality Int where
  isEqual 100 100     = True
  isEqual _ _         = False

main = do 
  print $ isEqual Red Green //Output: True
  print $ isEqual 100 100 //Output: Error Ambiguous type variable ‘a0’ arising from a use of ‘isEqual’
显然,当我指定
print$isEqual(100::Int)(100::Int)

为什么Haskell隐式地认识到
Red
Green
colors
但需要我将
100
绑定到
Int

Red
等是单形态值,即它们具有具体类型

Red :: Colour
因此,当
Red
出现在您的代码中时,编译器立即知道它是什么类型,并且可以使用此信息推断要用于什么类型的typeclass实例,例如
BasicEquality

OTOH,像
100
这样的数字文本具有多态类型
numa=>a
。原因是我们希望能够写作

Prelude> replicate 3 'q'
"qqq"
以及

Prelude> sqrt 3
1.7320508075688772
如果
3
仅具有类型
Int
,则后者将不起作用,因为
sqrt
需要一种类型,例如
Double
。因为数字文字实际上是多态的,所以这并不重要

您案例中的问题是,
isEqual
也是多态的。因此,编译器可以选择多种不同的类型。你也有这样的形象

instance BasicEquality Integer where
  isEqual 50 1000     = True
  isEqual _ _         = False
然后
isEqual 100 100
可以解释为
isEqual(100::Int)100
(即
True
)或
isEqual(100::Integer)100
(即false)

在实践中,这很少是一个问题,因为您不会比较不同的数字文字(这些文字已经知道,所以您可以简单地对结果进行硬编码!),但在您的程序中最多一个文字和一个变量,并且该变量通常已经具有根据上下文确定的类型。比如说,

*Main> let b = length "foobar"
*Main> isEqual 4 b
False
没有任何签名的作品。

Red
等为单态值,即它们具有具体类型

Red :: Colour
因此,当
Red
出现在您的代码中时,编译器立即知道它是什么类型,并且可以使用此信息推断要用于什么类型的typeclass实例,例如
BasicEquality

OTOH,像
100
这样的数字文本具有多态类型
numa=>a
。原因是我们希望能够写作

Prelude> replicate 3 'q'
"qqq"
以及

Prelude> sqrt 3
1.7320508075688772
如果
3
仅具有类型
Int
,则后者将不起作用,因为
sqrt
需要一种类型,例如
Double
。因为数字文字实际上是多态的,所以这并不重要

您案例中的问题是,
isEqual
也是多态的。因此,编译器可以选择多种不同的类型。你也有这样的形象

instance BasicEquality Integer where
  isEqual 50 1000     = True
  isEqual _ _         = False
然后
isEqual 100 100
可以解释为
isEqual(100::Int)100
(即
True
)或
isEqual(100::Integer)100
(即false)

在实践中,这很少是一个问题,因为您不会比较不同的数字文字(这些文字已经知道,所以您可以简单地对结果进行硬编码!),但在您的程序中最多一个文字和一个变量,并且该变量通常已经具有根据上下文确定的类型。比如说,

*Main> let b = length "foobar"
*Main> isEqual 4 b
False
作品没有任何签名。

“基本平等”是一种非常奇怪的平等形式。“基本平等”是一种非常奇怪的平等形式。