在esqueleto中乘以Int和double值?

时间:2015-07-02 15:06:44

标签: haskell esqueleto

我面临的问题非常简单:基本上我正在尝试计算Int和Double的乘积。在简单的Haskell中,我会运行

product = (fromIntegral int_val) * double_val

然而,我无法弄清楚如何在esqueleto中做到这一点。我有一个表B,它有一个Int类型的列“amount”和一个表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是Int,AId和BId是对表A和B的引用。

表C:Id |名称|价格, 这是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)

修改

我尝试过像这样使用fmapfromIntegral

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邮件列表上询问过这个问题。讨论可以在here找到。

2 个答案:

答案 0 :(得分:1)

我不是专家,但您可能会尝试将<div data-ng-bind-html="documentDetail.Content | unsafe"></div> 应用于整数参数:

_floor

这可能会将您的整数变为双精度,因为floor_ :: (..., PersistField a, Num a, PersistField b, Num b) => expr (Value a) -> expr (Value b) a可能不同。通常你用它来将双打变为整数,但它也可能反过来。

一些类似的Esqueleto函数也可以正常工作。

是的,这是一个黑客攻击。我希望有些专家可以提出更好的解决方案。

答案 1 :(得分:0)

如讨论here中所述,为此目的,现在(因为esqueleto版本2.2.9)castNum

castNum :: (Num a, Num b) => expr (Value a) -> expr (Value b)
相关问题