我面临的问题非常简单:基本上我正在尝试计算 Int 和 Double 的乘积。在普通的 Haskell 中,我会跑
product = (fromIntegral int_val) * double_val
但是我无法弄清楚如何在 esqueleto 中做到这一点。我有一个表 B 有一个 Int 类型的列“数量”和一个表 C 有一个 Double 类型的列“价格”。当尝试提取两者并计算产品时,像这样
(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)
这会导致两个错误:
No instance for (Functor SqlExpr)
和
No instance for (Num (Value Double))
正如评论中所建议的(@Thomas M. DuBuisson),我尝试了:
let product = fmap (fmap fromIntegral) (b ^. BAmount) *. (c ^. CPrice)
这解决了第二个问题,但我仍然得到No instance for (Functor SqlExpr)
.
编辑 2:
我在 Yesod 邮件列表上问过这个问题。可以在这里找到讨论。