假设我有以下模式:
Person
stackOverflowUser Bool
age Int Maybe使用Esqueleto (& Yesod),假设我希望获得Stack溢出用户的平均年龄。我想做一个带有类型签名的函数:
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)这给我带来了价值(也许是Int),但我需要理解“也许Int”。我试着做
mapM_ unValue userAge但出于某种原因,这样做会导致类型错误,给我可能()而不是可能的错误。此外,我认为上述代码的最后一行应该有:
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非常陌生,所以我很难搞清楚。
我想我可以使用原始SQL,但如果可能的话,我想使用Esqueleto。
发布于 2014-09-18 11:47:24
明白了!最后,我把头转到了类型错误上,并想出了如下结论:
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“似乎不会引起任何问题;我在空值和非空值上测试了它。我想“?”操作员是为其他情况保留的。
希望这能帮别人省点时间搞清楚!
https://stackoverflow.com/questions/25910490
复制相似问题