为什么Haskell在声明类实例时不允许使用类型同义词?
虽然我知道GHC中有一个扩展,但我不知道它有多“危险”,我想知道这个限制是否是任意的,有点像单态限制,或者是否有更深层次的原因。为什么Haskell在声明类实例时不允许使用类型同义词?,haskell,typeclass,Haskell,Typeclass,虽然我知道GHC中有一个扩展,但我不知道它有多“危险”,我想知道这个限制是否是任意的,有点像单态限制,或者是否有更深层次的原因。TypeSynonymInstances是完全安全的。由于不允许使用任何可能像部分应用的类型同义词这样的花哨内容,因此其效果与在实例头中键入类型同义词的右侧完全相同,即 type Foo a = ([a], [a]) instance Bar (Foo a) 与 instance Bar ([a], [a]) 但是,请注意,这两个实例都需要FlexibleInsta
TypeSynonymInstances
是完全安全的。由于不允许使用任何可能像部分应用的类型同义词这样的花哨内容,因此其效果与在实例头中键入类型同义词的右侧完全相同,即
type Foo a = ([a], [a])
instance Bar (Foo a)
与
instance Bar ([a], [a])
但是,请注意,这两个实例都需要FlexibleInstances
,因为它们包含嵌套的类型构造函数以及重复的类型变量。一般来说,扩展类型同义词后通常会出现这种情况
我认为这可能是他们被默认禁止的原因
然而,FlexibleInstances
也是一个非常安全的扩展。如果您试图定义重叠的实例,如
instance Xyzzy String
instance Xyzzy [a]
至于为什么
FlexibleInstances
在默认情况下不可用,我只能猜测这是为了简化语言。实例头的标准规则确保实例定义可以重叠的唯一方法是实例头中的类型构造函数相同,而使用FlexibleInstances
检查重叠稍微困难一些。据我所知,这有点像单态性的限制,摆脱它并没有什么错,但它会让你做出你可能意想不到的行为。就像单态限制不会损害任何东西一样,所有类型仍然有效,这也应该是完全安全的:对类型同义词的限制阻止它们做任何比简单的名称缩短更有趣的事情(例如,你永远不能部分应用它们,所以我们没有类型级别的lambda),所以你可以用它们定义的右边来代替它们。因此,由于这些定义的右侧可以作为实例头进行检查(或包含进一步的类型同义词进行扩展),因此不应该发生任何不安全的事情
另一方面,正如禁用单态限制会导致潜在的奇数性能特征一样,启用类型同义词实例也会导致潜在的奇数类型类错误。因此,让我们启用-XTypeSynonymInstances
,并尝试使用类型同义词编写实例:
Prelude> :set -XTypeSynonymInstances
Prelude> instance Num String where (+) = (++)
<interactive>:3:10:
Illegal instance declaration for `Num 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 -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Num String'
但事情很快变得糟糕:
Prelude> instance Eq String where
Prelude> "a" == "b"
<interactive>:8:5:
Overlapping instances for Eq [Char]
arising from a use of `=='
Matching instances:
instance Eq a => Eq [a] -- Defined in `GHC.Classes'
instance Eq String -- Defined at <interactive>:7:10
In the expression: "a" == "b"
In an equation for `it': it = "a" == "b"
Prelude>实例均衡字符串,其中
前奏曲>“a”=“b”
:8:5:
Eq[Char]的重叠实例
因使用“==”而产生
匹配实例:
实例Eq a=>Eq[a]--在“GHC.Classes”中定义
实例Eq字符串--定义时间:7:10
在表达式中:“a”==“b”
在“it”的方程式中:it=“a”=“b”
同样,尽管
String
看起来像是一个不同的类型,但我们已经有了[a]
的实例,因此这与它重叠。(事实上,这可能是-XFlexibleInstances
默认不启用的部分原因。)而启用-XOverlappingInstances
比启用-XFlexibleInstances
更重要,但为了减少Haskell给初学者带来的惊喜,它被禁止了
Prelude> instance Eq String where
Prelude> "a" == "b"
<interactive>:8:5:
Overlapping instances for Eq [Char]
arising from a use of `=='
Matching instances:
instance Eq a => Eq [a] -- Defined in `GHC.Classes'
instance Eq String -- Defined at <interactive>:7:10
In the expression: "a" == "b"
In an equation for `it': it = "a" == "b"