56

このタイプチェックを行う理由:

runST $ return $ True

以下はそうではありませんが:

runST . return $ True

GHCI は次のように訴えています。

Couldn't match expected type `forall s. ST s c0'
            with actual type `m0 a0'
Expected type: a0 -> forall s. ST s c0
  Actual type: a0 -> m0 a0
In the second argument of `(.)', namely `return'
In the expression: runST . return
4

3 に答える 3

52

簡単に言うと、型推論は常に上位の型で機能するとは限りません。この場合、 の型を推測することはできませんが(.)、明示的な型注釈を追加するかどうかを型チェックします。

> :m + Control.Monad.ST
> :set -XRankNTypes
> :t (((.) :: ((forall s0. ST s0 a) -> a) -> (a -> forall s1. ST s1 a) -> a -> a) runST return) $ True
(((.) :: ((forall s0. ST s0 a) -> a) -> (a -> forall s1. ST s1 a) -> a -> a) runST return) $ True :: Bool

($)独自のバージョンに置き換えると、最初の例でも同じ問題が発生します。

> let app f x = f x
> :t runST `app` (return `app` True)
<interactive>:1:14:
    Couldn't match expected type `forall s. ST s t0'
                with actual type `m0 t10'
    Expected type: t10 -> forall s. ST s t0
      Actual type: t10 -> m0 t10
    In the first argument of `app', namely `return'
    In the second argument of `app', namely `(return `app` True)'

繰り返しますが、これは型注釈を追加することで解決できます。

> :t (app :: ((forall s0. ST s0 a) -> a) -> (forall s1. ST s1 a) -> a) runST (return `app` True)
(app :: ((forall s0. ST s0 a) -> a) -> (forall s1. ST s1 a) -> a) runST (return `app` True) :: Bool

ここで起こっていることは、GHC 7 には標準($)演算子にのみ適用される特別な型付け規則があるということです。Simon Peyton-Jones は、GHC ユーザー メーリング リストへの返信で、この動作について説明しています。

これは、非予測型を処理できる型推論の動機付けとなる例です。のタイプを考えてみましょう($):

($) :: forall p q. (p -> q) -> p -> q

pこの例では、 でインスタンス化する必要があります。これが(forall s. ST s a)非予測的ポリモーフィズムの意味です。つまり、型変数をポリモーフィック型でインスタンス化することです。

悲しいことに、[これ] を補助なしで型チェックできる合理的な複雑さのシステムを私は知りません。複雑なシステムはたくさんあり、私は少なくとも 2 つの論文の共著者でしたが、GHC に住むにはあまりにも複雑すぎます。boxy 型の実装はありましたが、新しい型チェッカーを実装するときに取り出しました。誰もそれを理解していませんでした。

しかし、人々は非常に頻繁に書いています

runST $ do ... 

GHC 7 では、($). 明らかな型付け規則を備えた新しい構文形式と考え(f $ x)てください。

のようなルールがないため、2 番目の例は失敗します(.)

于 2012-02-27T18:09:23.027 に答える
36

このrunST $ do { ... }パターンは非常に一般的であり、通常は型チェックを行わないという事実は非常に煩わしいため、GHCはSTそれを機能させるためにいくつかの特定の型チェックハックを含めました。これらのハックは、おそらくここで($)バージョンに対して発生していますが、バージョンに対しては発生していません(.)

于 2012-02-27T17:57:13.907 に答える
3

メッセージは、ポイントを少し混乱させます (またはそう感じます)。あなたのコードを書き直してみましょう:

runST (return True)   -- return True is ST s Bool
(runST . return) True  -- cannot work

別の言い方をm0 a0すれば、モノモーフィック (a0 を取得する場合の return の結果) は (forall s.ST sa) と統合できないということです。

于 2012-02-27T18:02:31.653 に答える