说我有以下型号:
Person
stackOverflowUser Bool
age Int Maybe
使用Esqueleto(& Yesod),说我想获得Stack Overflow用户的平均年龄。我想创建一个带有类型签名的函数:
userAge :: Handler (Maybe Int)
到目前为止,我有以下内容:
userAge :: Handler [Value (Maybe Int)]
userAge = runDB $
select $
from $ \person -> do
where_ (person ^. PersonStackOverflowUser ==. val True)
return joinV $ avg_ (person ^. PersonAge)
这让我[Value(Maybe Int)],但我需要深入到#34; Maybe Int"。我试着做了
mapM_ unValue userAge
但由于某种原因,这样做会引发类型错误,给我[Maybe()]而不是[Maybe Int] ...另外,我认为上面代码中的最后一行应该有:
person ?. PersonAge
而不是
person ^. PersonAge
因为PersonAge可以为NULL,但更改它会给我一个类型错误,因为:
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很新,所以我&# 39;我无法搞清楚。
我想我可以使用原始SQL,但如果可能,我想使用Esqueleto来做这件事。
答案 0 :(得分:3)
知道了!最后我把头围绕着类型错误,想出了这个:
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))
&#34;人^。人士&#34;似乎没有引起任何问题;我在null和非null值上测试了它。我想&#34;?。&#34;运算符保留用于其他情况。
希望这可以节省其他人一些时间来搞清楚它!