質問

ContTや友人の意味を理解するためにクエストを継続。下記(不条理が、説明の)コードをご検討くださいます:

v :: IO (Either String [String])
v = return $ Left "Error message"

doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
    x <- liftIO $ v
    x2 <- either (k . Left) return x
    when True $ k (Left "Error message 2")
    -- k (Left "Error message 3")
    return $ Right () -- success

このコードはコンパイルされません。その下のコメントk個の呼び出しでwhenを交換する場合は、それがコンパイルされます。何が起こっているのですか?

私は×2行をコメントアウトした場合、

あるいは、それはまた、コンパイルされます。 ???

明らかに、これはすべての要素が目的にかなうように蒸留元のコードのバージョンとなります。何が起こっているのかについての説明の助けに感謝し、どのようにそれを修正します。おかげます。

役に立ちましたか?

解決

ここでの問題はwheneitherの種類、ないContTに特に何も関係しています:

when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c

二番目の引数には、いくつかのモナドm ()の型mであることが必要です。あなたのコードのwhenラインは、このようにそのように修正することができます:

when True $ k (Left "Error message 2") >> return ()

コードのコンパイルを行います。これは、あなたが何をしたいのか、おそらくありませんが、それは間違っているかもしれないものへと私たちにヒントを与える:kのタイプはwhenにまずいものになると推定されています。

次にeither署名用:eitherに2つの引数が同じタイプの結果を生成する関数でなければならないことに気付きます。 returnの種類は、ここでxに明示的に署名することによって固定され順番にあるvの種類によって決定されます。したがって(k . Left)ビットは、同じ型を持っている必要があります。これは、順番に

(GHC決定)でkのタイプを固定します
k :: Either String () -> ContT (Either String ()) IO [String]

このはwhenの期待と互換性がありません。

あなたはx2ライン、しかし、コードの型チェッカーのビューに及ぼす影響を除去するコメントアウトないので、kはもはや不便なタイプに強制さと種類を想定して自由である場合には、

k :: Either [Char] () -> ContT (Either [Char] ()) IO ()

これwhenの本で結構です。したがって、コードはコンパイルされます。

最後の注意点として、私は2つのシナリオの下でkの正確な種類を得るために、GHCiののブレークポイント機能を使用する - 私は手でそれらを書き、自分の正しさを保証どのような方法であることに十分な専門家の近くにどこにもよん。 :-)それを試してみること:break ModuleName line-number column-numberを使用します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top