儘管我知道GHC中有一個TypeSynonymInstances的擴展,但我不知道它有多「危險」,我不知道這個限制是否是任意的,有點像單態限制,或者是否有更深的原因。爲什麼Haskell在聲明類實例時不允許類型同義詞?
回答
TypeSynonymInstances
是完全安全的。因爲任何潛在的花式像部分應用類型同義詞不允許,它具有完全一樣在實例頭打字類型同義詞的右手側,即
type Foo a = ([a], [a])
instance Bar (Foo a)
相同的效果是一樣的
instance Bar ([a], [a])
但是,請注意,兩個實例都需要FlexibleInstances
,因爲它們包含嵌套類型構造函數以及重複類型變量。一般來說,擴展類型同義詞之後通常會出現這種情況。
我想可能是他們被默認禁止的原因。
然而,FlexibleInstances
也是一個非常安全的擴展。它能做的最糟糕的是會導致編譯時錯誤,如果你嘗試定義重疊的情況下,如
instance Xyzzy String
instance Xyzzy [a]
至於爲什麼FlexibleInstances
是默認不可用,我只能猜測,這是簡化的語言。實例頭的標準規則確保實例定義可以重疊的唯一方式是如果實例頭中的類型構造函數是相同的,而檢查重疊的稍微困難一些。
據我瞭解,它有點像單態限制 - 沒有什麼錯誤關於擺脫它,但它打開你的行爲,你可能不希望。就像單形態限制不會傷害任何東西 - 所有類型都是有效的 - 這也應該是完全安全的:無論如何都會限制類型同義詞,從而阻止它們做簡單的名稱縮寫(,例如,you不能部分應用它們,所以我們不會獲得類型級別的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'
String
看起來像一個普通的舊類型,所以這可能是在第一個令人驚訝的;但它確實是[Char]
,所以根據Haskell 2010嚴格的規則,這個實例是無效的。如果我們通過-XFlexibleInstances
轉彎轉放寬這些規則(順便說一下,implies -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
爲a much dodgier idea比開啓-XFlexibleInstances
。
它曾經被允許,但爲了讓Haskell減少對初學者的驚喜,它被禁止。
- 1. 不允許使用類型同義詞的類型實例
- 2. 聲明參數化類型同義詞的實例
- 3. 爲什麼TypeSynonymInstances不允許在實例頭中使用部分應用的類型同義詞?
- 4. Haskell類型同義詞
- 5. Haskell類型聲明
- 6. 要求類型類實例用於haskell關聯類型同義詞
- 7. 爲什麼多態類型同義詞不能像實例中的多態數據聲明一樣工作?
- 8. 爲什麼PHP不允許類具有同名的類和實例成員?
- 9. 這個錯誤的含義是什麼「聲明實例方法後不允許聲明實例字段」。
- 10. 多參數類型同義詞實例
- 11. 理解類型同義詞和參數化類型的同義詞在Haskell
- 12. 爲什麼java不允許創建內部類的實例?
- 13. 「類型同義詞實例是不允許的」,即使我有一個新類型單子變壓器
- 14. 多參數類型類實例聲明
- 15. 類型類,重載和實例聲明
- 16. 爲什麼這種類型不允許使用類型參數?
- 17. 爲什麼socketpair()允許SOCK_DGRAM類型?
- 18. 函數上需要實例聲明的Haskell類型上下文
- 19. 連接時允許的不同類型
- 20. 爲什麼在函數範圍中不允許類前向聲明?
- 21. 爲什麼C#不允許在實現接口時繼承返回類型
- 22. UML - 在方法中聲明類實例時什麼是關係
- 23. 爲什麼在類聲明中定義的類模板成員函數的顯式特殊化允許,但在單獨定義時不允許?
- 24. Haskell數據實例爲不透明數據類型
- 25. 聲明類型類的所有實例都在另一個類型類中,但不修改原始類聲明
- 26. 爲什麼在Play框架模板中定義的函數不允許聲明返回類型?
- 27. 爲什麼要找到類型聲明?
- 28. 什麼類型可以聲明爲const?
- 29. 爲什麼Java變量聲明中的類型不同?
- 30. 是否存在用於部分類型同義詞實例的Haskell(GHC)擴展?