Haskell: instances parameterized type 一种单一类型

Haskell: instances parameterized type one single type

我正在编写一些解析器代码,其中涉及参数化类型:

data Power i    = Power1 { charges :: i } | Power2 { charges :: i }

我知道类型 i 将始终是 Int(但已参数化,因为我需要它用于另一种类型 class)。
现在我想让我的 Power 类型从 Show 派生(以特定格式,所以我需要自己覆盖它)。据我所知,i 只会是 Int,我试过:

instance Show (Power Int) where
    show (Power1 0)    = ""
    show (Power1 i)    = "some formatting involving i\n"
    show (Power2 0)    = ""
    show (Power2 i)    = "some other formatting involving i\n"

但是,这不会编译,并显示消息

    • Illegal instance declaration for ‘Show (Power Int)’
        (All instance types must be of the form (T a1 ... an)
         where a1 ... an are *distinct type variables*,
         and each type variable appears at most once in the instance head.
         Use FlexibleInstances if you want to disable this.)
    • In the instance declaration for ‘Show (Power Int)’
   |
22 | instance Show (Power Int) where

为什么这不可能?

为什么这与编译器相比如此不同?

instance (Show i) => Show (Power i) where

您不能对类型使用类型约束,但对类型 classes。在您的示例中,可以为 Integral 类型 class 实例化 Show。然后 show 被定义为 Power IntPower Integer.

instance Integral a => Show (Power a) where
    show (Power1 0)    = ""
    show (Power1 i)    = "some formatting involving i\n"
    show (Power2 0)    = ""
    show (Power2 i)    = "some other formatting involving i\n"

GHC 说 All instance types must be of the form (T a1 ... an) where a1 ... an are *distinct type variables*。这是在 Haskell 98 中定义的。要将具有具体类型的数据类型作为 class 参数,需要 FlexibleInstances 扩展。因为存在包装实例问题。

例如:

newtype Foo a = Foo a

class Bar a where
    baz :: a -> a

instance Bar (Foo Int) where
    baz = ...

instance Show a => Bar (Foo a) where
    baz = ...

当您调用 baz 1 时,编译器会混淆版本是否应该调用。 1Int也属于Showclass!详情写在,大家有时间应该看看