GHC内にTypeSynonymInstancesという拡張子があることは知っていますが、どのように危険なのかわかりませんし、この制限が恣意的なのか、それとも一種の制限のようなものなのか、さらに深い理由があるのでしょうか。なぜHaskellはクラスインスタンスを宣言するときに型シノニムを許可しないのですか?
答えて
TypeSynonymInstances
は完全に安全です。部分的に適用されるタイプの同義語のような潜在的に派手なものは禁止されているので、それはすなわち、インスタンス頭部に
type Foo a = ([a], [a])
instance Bar (Foo a)
を型シノニムの右側を入力するのとまったく同じ効果を
と同じされていますinstance Bar ([a], [a])
ただし、両方のインスタンスにはネストされた型コンストラクタと繰り返し型変数が含まれているため、両方のインスタンスにはFlexibleInstances
が必要です。一般に、これはタイプ同義語を拡張した後のケースであることが多い。
私は彼らがデフォルトでは禁止されている理由が考えられます。
しかし、FlexibleInstances
も完全に安全な拡張です。それが行うことができます最悪の事態はあなたがそのような、私はそれが言語を簡単にするためにだと推測できるFlexibleInstances
はデフォルトでは使用できない理由については
instance Xyzzy String
instance Xyzzy [a]
として重複インスタンスを定義しようとした場合、コンパイル時にエラーが発生しています。インスタンスヘッドの標準ルールは、インスタンスの定義がオーバーラップできる唯一の方法は、インスタンスヘッド内の型コンストラクタが同一で、重複をチェックするFlexibleInstances
が少し難しいことを保証することです。私はそれを理解したよう
は、それは一種の単相性のようなものです制限 - そこは何もそれを退治について間違っはませんが、それはあなたが期待していない可能性があります行動にあなたを開きます。単相性制限は何も害を及ぼさないのと同じように、すべての型はまだ有効です。これは完全に安全でなければなりません。型の同義語には制限があり、単純な名前の短縮よりも好奇心をそそることはできません。(、それらを部分的に適用することはできないので、タイプレベルのラムダは得られません)、その定義の右側でいつでも置き換えることができます。したがって、これらの定義の右辺はインスタンス・ヘッドとしてチェックされることができます(または展開するためにさらにタイプ・シノニムを含んでいます)ので、安全でないことは起こりません。
一方、monomorphismの制限を無効にすると、潜在的に奇妙なパフォーマンス特性が現れます。タイプ同義語インスタンスを有効にすると、奇妙なタイプのクラスエラーが発生する可能性があります。それでは、-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
をオンにすると、-XFlexibleInstances
をオンにするよりもa much dodgier ideaになります。
これまで許可されていましたが、初心者にはハスケルの驚きを少なくするため、禁止されました。
- 1. Haddockの型シノニムの宣言を隠す
- 2. 空の宣言はなぜ許可されますか?
- 3. Haskellの型宣言
- 4. Haskellの型宣言
- 5. 値コンストラクタで宣言された型がHaskell型でないのはなぜですか?
- 6. System.Drawing.Color型の定数を宣言できないのはなぜですか?
- 7. 型宣言構文haskellとhaskellのような言語の違い
- 8. なぜC#は型パラメータをデフォルトパラメータとして許可しないのですか?
- 9. マップとしてクラス名を宣言できないのはなぜですか?
- 10. 型シノニムを1桁で宣言し、複数のファイルで使用する
- 11. 宣言型サービスを参照していない宣言型サービス
- 12. 外部宣言を型として使用できないのはなぜですか?
- 13. Haskell多形性と型クラスインスタンス
- 14. Haskellのデータ宣言を型の値でバインドすることができます
- 15. 静的型付き言語で型の宣言が重要なのはなぜですか?
- 16. 型エイリアス宣言のHaskell型クラス
- 17. PHP変数の型をコメントに宣言するのはなぜですか?
- 18. 式のパレットに型宣言を使用するのはなぜですか?
- 19. 'anyTextString'型の変数をTypeScriptで宣言することはなぜ可能ですか?
- 20. なぜsqlalchemy宣言型APIを使用しますか?
- 21. クラス内に文字列を宣言できないのはなぜですか?
- 22. なぜこのコードはDISTINCT型を宣言していますか?
- 23. なぜdocument.createTextNode()はsetAttribute()を許可しないのですか?
- 24. ポインタ宣言にデータ型が必要なのはなぜですか?
- 25. 複数のconstをJavaScriptで宣言できないのはなぜですか?
- 26. functionでclassを宣言しているときにconstと&を使用するのはなぜですか?
- 27. 関数型をhaskellの関数定義で宣言する
- 28. なぜ私はmap.entry <k,v>を型として使用することはできませんか?可変宣言で可能です
- 29. F#で関数内で型を宣言できないのはなぜですか?
- 30. 宣言でクラスメンバーを初期化できないのはなぜですか?