我正在尝试将Int
定义为我的类型类Add
的实例。我想定义自己的运算符+++
,该运算符应在整数和字符串上重载。我的目标是能够使用相同的运算符添加整数并连接字符串。因此,我使用实例Add
和Int
创建了类型类[char]
:
class Add a where
(+++) :: a -> a -> a
instance Add Int where
x +++ y = x + y
instance Add [char] where
x +++ y = x ++ y
问题:在计算表达式1 +++ 2
时,GHCi给我以下错误消息:
<interactive>:9:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 18 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
但是将Integer
定义为Add
的实例时
instance Add Integer where
x +++ y = x + y
GHCi可以将1 +++ 2
评估为3
,但我没有收到错误。
问题:使用Int
作为实例时,为什么不起作用?使用Int
或Integer
有什么区别?
鉴于它适用于Integer
,但不适用于Int
,我很确定这是由于“类型默认值”所致。
在GHCi中(在较小程度上在编译的代码中),如果表达式的类型不明确,则编译器将尝试几种“默认类型”,其中的默认值为Integer
(但not Int
) 。几乎可以肯定这就是差异的来源。
我怀疑如果在表达式的末尾添加:: Int
,它将很好地执行。问题不是存在类型error,而是可能存在多个类型,并且编译器不确定您打算使用哪种类型。
我从未尝试过,但是我相信您可以通过说default (Int, Double)
之类的内容来更改默认值。 (通常是default (Integer, Double)
。)我认为这是正确的语法。不确定100%。
GHCi手册中对此有一些说明:https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#type-defaulting-in-ghci
还有Haskell报告:https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3(第4.3.4节)