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'
そして今、私の質問:
m ~ IO とはどういう意味ですか? エラーの最初の 2 行は何を示していますか? また、haskell コードでこの ~ 構造を見ましたが、それが何であるかを見つけることができません。拡大?リジッド型変数とは?
エラーを見つけて修正しました。
liftIO $
前に削除するだけで十分scope
です。しかし、それは試行と再コンパイルのサイクルに過ぎませんでした。このエラー メッセージのどこにエラーの場所が示されていますか? 「fn」に何か問題があります。わかりました、少し考えて推測しました: GHC は上から下に型を推論します。liftIO
そして、それを使用することm
から推測しましIO
たfn
が、一般的なタイプm
であるため、エラーです。上から下まで推論するHaskell コンパイラはありますか? そして (もっと重要なことに) GHC が出力の部分式について推論する型を見ることはできますか?
この長い質問を読んでくれてありがとう!