Haskell `实例`用于具体类型而不是typeclass?

Haskell `实例`用于具体类型而不是typeclass?,haskell,typeclass,Haskell,Typeclass,我定义了一个简单的列表类型: data MyList a = End |Entry a (MyList a) 而不是派生(Show)我为所有MyList a明确地实现了这一点,其中a是Show的一个实例 instance Show a => Show (MyList a) where show End = "" show (Entry a l) = (show a) ++","++(show l) 这个很好用。现在我想改变这种情况,只有

我定义了一个简单的列表类型:

data MyList a = End
               |Entry a (MyList a)
而不是
派生(Show)
我为所有
MyList a
明确地实现了这一点,其中
a
Show
的一个实例

instance Show a => Show (MyList a)
  where show End = ""
        show (Entry a l) = (show a) ++","++(show l)
这个很好用。现在我想改变这种情况,只有
MyList String
Show
的一个实例,为此我编写了

instance Show (MyList String)
  where show End = ""
        show (Entry a l) = a ++","++(show l)
但这导致了一个错误,我不理解:

Illegal instance declaration for `Show (MyList String)'
  (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 (MyList String)'

有人能解释一下为什么这不起作用,以及这个错误告诉我什么吗?

这个错误告诉您,standard Haskell不允许这种实例定义。正如上面所说,

所有实例类型的格式必须为(T a1…an)
其中a1。。。A是*不同类型的变量*,
每个类型变量在实例头中最多出现一次。
其中一个原因是,如果您同时保留两个实例定义,编译器将不知道为
MyList String
选择哪一个,因为它们都匹配。(您可能还想看一下。)

在实例类型的形式上有这样的约束可以保证类型检查总是终止的,当然也有一些有效的、可类型检查的程序的实例不是这种形式的,这就是它的工作原理:Haskell中的一些限制是保守的


在您的特定情况下,只需按照编译器的建议执行(即启用
FlexibleInstances
)即可实现此功能,并且此扩展在终止方面是安全的。

因此,如果不启用
FlexibleInstances
,我只能对整个类型类执行
显示
,而对特定类型的构造函数则不行(例如,您的
MyList::*->*
)您只能为整个“类型族”实现类(例如
Show
)形式为
MyList a
,而不是针对特定的个人,如
MyList String
MyList Bool
。顺便说一句,这正是
Show
具有hacky方法的原因。您希望显示
Char
列表与所有其他类型的列表不同,但您不能只实现separate
在标准Haskell中显示[Char]
实例。