1

Rank-N-Types のHaskell wiki ページは、この型を示しています

forall a . a -> (forall b . b -> a)

はランク 1 です。私はこの事実を信じており、それは私にとって非常に理解できるように思えます (関数のランクを決定する方法について既に知っていることを念頭に置いてください)。ただし、次のコードを記述しようとすると:

{-# LANGUAGE ExplicitForAll #-}

foo :: forall a . a -> (forall b . b -> a)
foo = undefined

コンパイルされず (ghc 8.0.1)、次のエラーが発生します:

• Illegal polymorphic type: forall b. b -> a
  Perhaps you intended to use RankNTypes or Rank2Types
• In the type signature:
    foo :: forall a. a -> (forall b. b -> a)

だから私は疑問に思います:fooタイプは本当にランク 2 を持っていますか? それとも、関数の真のランクを検出するスマートなメカニズムが GHC にないのでしょうか? 教育目的で、関数型の真のランクを検査するghciようなコマンドが必要な場合があります...rank

ghci> :rank foo
foo :: forall a . a -> (forall b . b -> a)  -- Rank 1
4

1 に答える 1

3

この動作の理由は、タイプチェッカーのTcValidityモジュールに記載されています。

Note [Higher rank types]
~~~~~~~~~~~~~~~~~~~~~~~~
Technically
            Int -> forall a. a->a
is still a rank-1 type, but it's not Haskell 98 (Trac #5957).  So the
validity checker allow a forall after an arrow only if we allow it
before — that is, with Rank2Types or RankNTypes

私は優れた言語弁護士ではありませんが、Haskell 98 の仕様では、矢印の後の量指定子が禁止されているように見えますが、これはランク 1 の要件よりも厳しい要件です。Haskell 2010 は仕様を軽く更新しただけなので、これは 2010 にも当てはまると思います。

let r1 = LimitedRank True r0GHC がこれをエンコードする方法は、関数内のa を使用することだと思います (確かではありません)。これは、型宣言の先頭に scheckValidTypeを指定forallできますが、後続の関数引数はランク 0 でなければならないため、型内の the を除外forall b. b -> aします。

標準免責事項:私は専門家ではありません。私が持っていたのはgithub検索だけでした

于 2016-12-18T18:12:42.987 に答える