簡體   English   中英

為什么Haskell在聲明類實例時不允許使用Type Synonyms?

[英]Why does Haskell not allow Type Synonyms when declaring class instances?

雖然我知道GHC中有一個TypeSynonymInstances擴展,我不知道它是多么“危險”,我想知道這種限制是否是任意的,有點像單態限制,或者是否有更深層次的原因。

TypeSynonymInstances非常安全。 由於不允許任何可能像部分應用類型同義詞一樣的奇特,它與在實例頭中鍵入類型同義詞的右側具有完全相同的效果,即

type Foo a = ([a], [a])
instance Bar (Foo a)

是相同的

instance Bar ([a], [a])

但請注意,兩個實例都需要FlexibleInstances因為它們包含嵌套類型構造函數以及重復類型變量。 通常,在擴展類型同義詞之后通常會出現這種情況。

我想可能是他們默認不被禁止的原因。

但是, FlexibleInstances也是一個非常安全的擴展。 如果你試圖定義重疊的實例,它可以做的最糟糕的是導致編譯時錯誤

instance Xyzzy String
instance Xyzzy [a]

至於為什么FlexibleInstances默認不可用,我只能猜測它是為了簡化語言。 實例定義的標准規則確保實例定義可以重疊的唯一方式是實例頭中的類型構造函數是否相同,而使用FlexibleInstances檢查重疊則稍微困難一些。

據我了解,它有點像單態限制 - 擺脫它沒有什么不對 ,但它打開了你可能沒想到的行為。 就像單同性限制不會傷害任何東西 - 所有類型仍然有效 - 這也應該是完全安全的:無論如何,類型同義詞都有限制,阻止他們做比簡單名稱縮短更好的事情( 例如 ,你永遠不能部分應用它們,所以我們沒有獲得類型級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'

String看起來像一個普通的舊類型,所以這一開始可能會令人驚訝; 但它真的是[Char] ,所以根據Haskell 2010嚴格的規則,這個實例是無效的。 如果我們通過啟用-XFlexibleInstances (順便-XTypeSynonymInstances暗示-XTypeSynonymInstances )來放寬這些規則,這個示例現在可以正常工作:

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

但事情變得很難看:

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"

同樣,即使String看起來像一個不同的類型,我們已經有[a]的實例,所以這與它重疊。 (事實上,這可能是為什么部分-XFlexibleInstances是不是在默認情況下)並打開-XOverlappingInstances一個更dodgier想法比打開-XFlexibleInstances

它曾經被允許,但是為了讓Haskell對初學者不那么充滿驚喜,它被禁止了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM