The problem I'm facing is pretty simple: Basically I'm trying to calculate the product of an Int and a Double. In plain Haskell I would just run
product = (fromIntegral int_val) * double_val
However I can't figure out how to do it in esqueleto. I'm having a table B that has a column "amount" of type Int and a table C that has a column "price" of type Double. When trying to extract both and calculate the product, like this
(b ^. BAmount) *. (c ^. CPrice)
I'm getting a type error (as expected):
Couldn't match type ‘Double’ with ‘Int’
Expected type: EntityField Drink Int
Actual type: EntityField Drink Double
I couldn't find anything in the docs that helped me and I actually have no idea how to go on. (For more code see the full example below).
Possible Solution: I could of course just store the price as an Int, but I'm interested if this can be done with esqueleto.
Full example:
Database:
Table A: Id|Name
Table B: Id|AId|BId|Amount where Amount is an Int and AId and BId are references to Table A and B.
Table C: Id|Name|Price , here is Price a Double
The query I've written is as follows:
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)
EDIT:
I've tried using fmap
and fromIntegral
like this:
let product = fmap fromIntegral (b ^. BAmount) *. (c ^. CPrice)
which results in two errors:
No instance for (Functor SqlExpr)
and
No instance for (Num (Value Double))
As suggested in the comments (by @Thomas M. DuBuisson), I tried:
let product = fmap (fmap fromIntegral) (b ^. BAmount) *. (c ^. CPrice)
which solves the second problem, but I still get No instance for (Functor SqlExpr)
.
EDIT 2:
I've asked about this on the Yesod mailing list. The discussion can be found here.