为什么Haskell在声明类实例时不允许使用Type Synonyms?

hug*_*omg 32 haskell typeclass

虽然我知道GHC 中有一个TypeSynonymInstances扩展,我不知道它是多么"危险",我想知道这种限制是否是任意的,有点像单态限制,或者是否有更深层次的原因.

ham*_*mar 25

TypeSynonymInstances非常安全.由于不允许任何可能像部分应用类型同义词一样的奇特,它与在实例头中键入类型同义词的右侧具有完全相同的效果,即

type Foo a = ([a], [a])
instance Bar (Foo a)
Run Code Online (Sandbox Code Playgroud)

是相同的

instance Bar ([a], [a])
Run Code Online (Sandbox Code Playgroud)

但请注意,两个实例都需要,FlexibleInstances因为它们包含嵌套类型构造函数以及重复类型变量.通常,在扩展类型同义词之后通常会出现这种情况.

我想可能是他们默认不被禁止的原因.

但是,FlexibleInstances也是一个非常安全的扩展.如果你试图定义重叠的实例,它可以做的最糟糕的是导致编译时错误

instance Xyzzy String
instance Xyzzy [a]
Run Code Online (Sandbox Code Playgroud)

至于为什么FlexibleInstances默认情况下不可用,我只能猜测它是为了简化语言.实例头的标准规则确保实例定义可以重叠的唯一方法是实例头中的类型构造函数是否相同,而FlexibleInstances检查重叠则稍微困难一些.


Ant*_*sky 17

据我了解,它有点像单态限制 - 摆脱它没有什么不对,但它打开了你可能没想到的行为.就像单同性限制不会伤害任何东西 - 所有类型仍然有效 - 这也应该是完全安全的:无论如何都有类型同义词的限制,这阻止他们做比简单的名称缩短更好的事情(例如,你永远不能部分应用它们,所以我们没有得到类型级别的lambdas),因此你总是可以用它们定义的右侧替换它们.因此,由于这些定义的右侧可以作为实例头检查(或包含进一步扩展的类型同义词),因此不应该发生任何不安全的事情.

在另一方面,正如禁用单态的限制可能让你潜在奇性能特点,使型代名词情况下,可能让你潜在的奇型类的错误.因此,让我们启用-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'
Run Code Online (Sandbox Code Playgroud)

String看起来像一个普通的旧类型,所以这一开始可能会令人惊讶; 但实际上[Char],根据Haskell 2010的严格规定,这个实例无效.如果我们通过打开-XFlexibleInstances(通常是暗示-XTypeSynonymInstances)来放松这些规则,这个例子现在有效:

Prelude> :set -XFlexibleInstances
Prelude> instance Num String where (+) = (++)
... errors about undefined methods ...
Prelude> "a" + "b"
"ab"
Run Code Online (Sandbox Code Playgroud)

但事情变得很难看:

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"
Run Code Online (Sandbox Code Playgroud)

同样,即使String看起来像一个不同的类型,我们已经有了一个实例[a],所以这与它重叠.(事实上,这可能是为什么部分-XFlexibleInstances不是在默认情况下)并打开-XOverlappingInstances一个更dodgier想法比打开-XFlexibleInstances.


aug*_*tss 6

它曾经被允许,但是为了让Haskell对初学者不那么充满惊喜,它被禁止了.