私が直面している問題は非常に単純です。基本的に、Int と Double の積を計算しようとしています。プレーンな Haskell では、実行するだけです
product = (fromIntegral int_val) * double_val
しかし、esqueleto でそれを行う方法がわかりません。Int 型の列「金額」を持つテーブル B と、Double 型の列「価格」を持つテーブル C があります。両方を抽出して積を計算しようとすると、このように
(b ^. BAmount) *. (c ^. CPrice)
タイプエラーが発生します(予想どおり):
Couldn't match type ‘Double’ with ‘Int’
Expected type: EntityField Drink Int
Actual type: EntityField Drink Double
私を助けてくれたドキュメントには何も見つかりませんでした。実際にどうすればよいのかわかりません。(詳細なコードについては、以下の完全な例を参照してください)。
考えられる解決策: もちろん、価格を Int として保存することもできますが、これが esqueleto で実行できるかどうかに興味があります。
完全な例:
データベース:
表 A: ID|名前
表 B: Id|AId|BId|Amount で、Amount は Int で、AId と BId は表 A と B への参照です。
表 C: Id|Name|Price 、これは Price a Double です
私が書いたクエリは次のとおりです。
result <- liftIO $ runDb $ select $
from $ \(a, b, c) -> do
where_ (a ^. AId ==. b ^. BAId)
where_ (b ^. BCId ==. c ^. CId)
let product = (b ^. BAmount) *. (c ^. CPrice)
let total = sum_ product :: SqlExpr (Value (Maybe Double))
groupBy $ a ^. AName
return (a ^. AName)
編集:
私はこのように使用してみましfmap
たfromIntegral
:
let product = fmap fromIntegral (b ^. BAmount) *. (c ^. CPrice)
その結果、次の 2 つのエラーが発生します
No instance for (Functor SqlExpr)
。
No instance for (Num (Value Double))
コメント(@Thomas M. DuBuissonによる)で示唆されているように、私は試しました:
let product = fmap (fmap fromIntegral) (b ^. BAmount) *. (c ^. CPrice)
これで 2 番目の問題は解決しますが、それでもNo instance for (Functor SqlExpr)
.
編集2:
これについては、Yesod メーリング リストで質問しました。議論はここで見つけることができます。