我定义了一个简单的列表类型:
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)'
谁能解释一下为什么这不起作用以及这个错误告诉我什么?
最佳答案
该错误告诉您标准 Haskell 不允许这种实例定义。正如它所说,
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.
原因之一是,如果您保留两个实例定义,编译器将不知道为 MyList String
选择哪一个,因为它们都匹配。 (您可能还想查看 rules for overlapping instances 。)
对实例类型的形式进行这种约束可以保证类型检查始终终止,虽然当然存在具有非这种形式的实例的有效且可类型检查的程序,但这就是它的工作原理:Haskell 中的一些限制是保守的。
在您的特定情况下,只需执行编译器建议的操作(即启用FlexibleInstances
)即可解决问题,并且此扩展在终止方面是安全的。
关于haskell - `instance` 代表具体类型而不是类型类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44590358/