これはHaskell 2010標準の一部ではないため、デフォルトではオンではなく、代わりに言語拡張として提供されています。なぜそれが標準にないのかについては、rank-n型は、標準のHaskellが持つ普通のrank-1型よりも実装するのがかなり困難です。それらは頻繁に必要とされるものではないので、委員会は言語と実装の単純さの理由からそれらを気にしないことにしました。
もちろん、ランクn型は有用ではありません。彼らは非常にそうであり、それらなしではST
monadのような貴重なツールはありません(IO
のような効率的でローカルな可変状態を提供します)。IORef
を使用してください。しかし、これらは言語にかなりの複雑さを加えます。そして、見た目の良さのようなコード変換を適用すると、不思議な動作を引き起こす可能性があります。たとえば、ランクn型チェッカーの中には、runST (do { ... })
が許可されますが、2つの式が常にランクn型なしで同等であっても、runST $ do { ... }
は拒否されます。予期しない(場合によっては厄介な)動作の例については、this SO questionを参照してください。
sepp2kを尋ねるように、あなたが代わりに求めている、場合forall
が明示的に増加した汎用性を得るために署名を入力して追加する必要がある理由は、問題が(forall x. x -> f x) -> (a, b) -> (f a, f b)
が実際に(x -> f x) -> (a, b) -> (f a, f b)
よりも限定型であることです。後者では、x -> f x
(任意のf
とx
)の形式の関数を渡すことができますが、前者では、渡す関数はすべてx
の関数でなければなりません。したがって、たとえば、タイプString -> IO String
の関数は、2番目の関数には許容される引数ですが、最初の関数は許容されません。代わりにタイプa -> IO a
が必要です。後者が自動的に前者に変換されたのはかなり混乱します!彼らは2つの非常に異なるタイプです。それは暗黙のforall
秒でより多くの意味をなすかもしれない
は、明示的に:
forall f x a b. (x -> f x) -> (a, b) -> (f a, f b)
forall f a b. (forall x. x -> f x) -> (a, b) -> (f a, f b)
なぜ拡張子がデフォルトでオンでないのか、なぜ '(x - > fx) - >(a、b) - >(fa、fb) 'は(forall x。x - > fx) - >(a、b) - >(fa、fb)'と同じように扱われません。後者の場合は、コンパイラが 'forall'をどこに挿入するかを決定するロジックを指定できますか? – sepp2k
後者ですが、私はこの件に関して全く何も提案し始めるべきではありません! –
'(x - > f x) - >(a、b) - >(f a、f b)'という型はかなり役に立たないことに注意してください。関数はタプルのいずれかの要素に第1引数を適用できないため、結果は '⊥'または'(⊥、⊥) 'でなければなりません。 – hammar