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.
As mentioned in the discussion here there is now (since esqueleto version 2.2.9) castNum for this purpose:
castNum :: (Num a, Num b) => expr (Value a) -> expr (Value b)