首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Esqueleto中集合函数的结果

Esqueleto中集合函数的结果
EN

Stack Overflow用户
提问于 2014-09-18 10:42:53
回答 1查看 433关注 0票数 3

假设我有以下模式:

代码语言:javascript
复制
Person
    stackOverflowUser Bool
    age Int Maybe

使用Esqueleto (& Yesod),假设我希望获得Stack溢出用户的平均年龄。我想做一个带有类型签名的函数:

代码语言:javascript
复制
userAge :: Handler (Maybe Int)

到目前为止,我有以下几点:

代码语言:javascript
复制
userAge :: Handler [Value (Maybe Int)]
userAge = runDB $
    select $
    from $ \person -> do
    where_ (person ^. PersonStackOverflowUser ==. val True)
    return joinV $ avg_ (person ^. PersonAge)

这给我带来了价值(也许是Int),但我需要理解“也许Int”。我试着做

代码语言:javascript
复制
mapM_ unValue userAge

但出于某种原因,这样做会导致类型错误,给我可能()而不是可能的错误。此外,我认为上述代码的最后一行应该有:

代码语言:javascript
复制
person ?. PersonAge

而不是

代码语言:javascript
复制
person ^. PersonAge

因为PersonAge可以是NULL,但是更改它会导致类型错误,因为:

代码语言:javascript
复制
avg_ :: (PersistField a, PersistField b) => expr (Value a) -> expr (Value (Maybe b))
(^.) :: (PersistEntity val, PersistField typ) => expr (Entity val) -> EntityField val typ -> expr (Value typ)
(?.) :: (PersistEntity val, PersistField typ) => expr (Maybe (Entity val)) -> EntityField val typ -> expr (Value (Maybe typ))

这可能比我想象的要容易,但是我在Esqueleto中找不到使用聚合函数的例子,而且我对Haskell非常陌生,所以我很难搞清楚。

我想我可以使用原始SQL,但如果可能的话,我想使用Esqueleto。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-18 11:47:24

明白了!最后,我把头转到了类型错误上,并想出了如下结论:

代码语言:javascript
复制
import Safe (headMay)
import Control.Monad (join)
import Database.Esqueleto
-- other misc Yesod imports

userAge :: Handler (Maybe Int)
userAge = do
    a <- runDB $ select $
                 from $ \person -> do
                 where_ (person ^. PersonStackOverflowUser ==. val True)
                 return $ joinV $ avg_ (person ^. PersonAge)
    return $ join (headMay (map unValue a))

"person ^. PersonAge“似乎不会引起任何问题;我在空值和非空值上测试了它。我想“?”操作员是为其他情况保留的。

希望这能帮别人省点时间搞清楚!

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25910490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档