この質問はgroundhog
またはに関するものですpersistent
。どちらも同じ問題を共有していると私は信じているからです。
Tr m a
いくつかの機能を提供するトランスがあるとしますf :: Int -> Tr m ()
。この機能には、データベースへのアクセスが必要です。ここで使用できるオプションはいくつかありますが、満足できるものはありません。
DbPersist
のどこかに変圧器を置くことができTr
ます。実際には、標準のトランスフォーマーのインスタンスがなく、さらにnewtypePersistBackend
のインスタンスを作成する必要があるため、これを一番上に配置する必要があります。Tr
クラスが最小からかけ離れているため、これはすでにひどいものです。私が行うすべての db アクションを持ち上げることもできます。
もう 1 つのオプションは、 の署名を に変更するf
ことPersistBackend m => Int -> Tr m ()
です。これもまた、私のnewtype でPersistBackend
インスタンスを作成するか、リフティングする必要があります。Tr
ここからが本当の問題です。すでに制約Tr
があるコンテキスト内で実行するにはどうすればよいですか? PersistBackend
と共有する方法はありませんTr
。
最初のオプションを実行して、いくつかの新しい接続プールDbPersist
内で実際のトランスフォーマーを実行するTr
ことができます (私が既にいるコンテキストからプールを取得する方法がないことがわかる限りPersistBackend
)、または 2 番目のオプションを実行することができます。実行関数を にしますrunTr :: PersistBackend m => Tr m a -> m a
。2番目のオプションは実際には完全に問題ありませんが、ここでの問題は、DbPersist
最終的にスタックのどこかになければならない が、現在トランスフォーマーの下にあり、構成されている標準トランスフォーマーのインスタンスTr
がないことです。PersistBackend
Tr
ここで正しいアプローチは何ですか?現時点では、ReaderT
リクエストに応じて接続プールを提供するスタックのどこかにセパタレrunDbConn
を使用し、DB にアクセスしたいすべての場所でそのプールを使用するのが最善の選択肢のようです。DbPersist
基本的にすでにそれがいかに重要であるかを見ると、ReaderT
それをしなければならないことに意味がありません。