2

IOモナドで実行される関数がありました:

withDB :: (forall c. IConnection c => c -> IO b) -> IO b
withDB fn = bracket (connectSqlite3 "int/db.sqlite3") disconnect fn

そして今、私はそれを一般化していくつかのMonadIO m. 私は次のようにして、私のものを再発明bracketしましたscope(ライブラリからいくつか知っていますか?):

scope :: MonadIO m => m a -> (a -> m b) -> (a -> m c) -> m c
scope before after action = do
    x <- before
    r <- action x
    _ <- after x
    return r

withDB :: MonadIO m => (forall c. IConnection c => c -> m b) -> m b
withDB fn = liftIO $ scope
                       (liftIO $ connectSqlite3 "int/db.sqlite3")
                       (\x -> liftIO $ disconnect x) fn

エラーが発生しました:

Could not deduce (m ~ IO)
from the context (MonadIO m)
  bound by the type signature for
    withDB :: MonadIO m => (forall c. IConnection c => c -> m b) -> m b
  at src\...
  'm' is a rigid type variable bound by
    the signature for
      withDB :: MonadIO m => (forall c. IConnection c => c -> m b) -> m b
Expected type: IO b
  Actual type: m b
In the third argument of 'scope' namely 'fn'
In the second argument of '($)', namely
  'scope
    (liftIO $ connectSqlite3 "int/db.sqlite3")
    (\x -> liftIO $ disconnect x)
    fn'

そして今、私の質問:

  1. m ~ IO とはどういう意味ですか? エラーの最初の 2 行は何を示していますか? また、haskell コードでこの ~ 構造を見ましたが、それが何であるかを見つけることができません。拡大?リジッド型変数とは?

  2. エラーを見つけて修正しました。liftIO $前に削除するだけで十分scopeです。しかし、それは試行と再コンパイルのサイクルに過ぎませんでした。このエラー メッセージのどこにエラーの場所が示されていますか? 「fn」に何か問題があります。わかりました、少し考えて推測しました: GHC は上から下に型を推論します。liftIOそして、それを使用することmから推測しましIOfnが、一般的なタイプmであるため、エラーです。上から下まで推論するHaskell コンパイラはありますか? そして (もっと重要なことに) GHC が出力の部分式について推論する型を見ることはできますか?

この長い質問を読んでくれてありがとう!

4

1 に答える 1

4

liftIO :: (MonadIO m) => IO a -> m aIOアクションを実行するので、 ということは、タイプが である必要があるliftIO $ scope ...ことを意味します。つまり、引数はモナドを使用する必要があります。を使用すると、 that must beが保証されるため、このタイプをコンテキストに持つと考えることができます。scope ...IO bscopeIOscopemIOscope

scope :: IO a -> (a -> IO b) -> (a -> IO c) -> IO b

このため、呼び出し内のsは何もしませliftIO。それらは単に からに変換しているだけであり、 ではなくで機能するため、 を使用することはできません。で実行するのではなく ( で実行されるため不可能です)、そのアクションをで実行するのではなく、 で直接実行されるため、固定された it を削除します。scopeIO aIO afnmIOliftIOscopemIOfnmm

于 2012-05-17T14:58:08.557 に答える