将 Int 定义为类型 class in Haskell 的实例时出现问题

Problem when defining Int as an instance of a type class in Haskell

我正在尝试将 Int 定义为我的类型 class Add 的实例。 我想定义我自己的运算符 +++,它应该在整数和字符串上重载。我的目标是能够使用相同的运算符添加整数和连接字符串。因此我用实例 Int[char]:

创建了类型 class Add
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作为实例时不起作用?使用 IntInteger 有什么区别?

鉴于它适用于 Integer 但不适用于 Int,我相当确定这是由于 "type defaulting".

在 GHCi 中(在较小程度上在编译代码中),如果一个表达式具有不明确的类型,编译器会尝试几个 "default types",其中 Integer(但 不是 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 节)