Say I have the following model:
Person
stackOverflowUser Bool
age Int Maybe
Using Esqueleto (& Yesod), say I want to get the average age of Stack Overflow users. I'd like to make a function with the type signature:
userAge :: Handler (Maybe Int)
So far, I have the following:
userAge :: Handler [Value (Maybe Int)]
userAge = runDB $
select $
from $ \person -> do
where_ (person ^. PersonStackOverflowUser ==. val True)
return joinV $ avg_ (person ^. PersonAge)
That gets me [Value (Maybe Int)], but I need to get down to "Maybe Int". I tried doing
mapM_ unValue userAge
But for some reason, doing so raised a type error, giving me [Maybe ()] rather than [Maybe Int]... Additionally, I think that the last line in the above code should have:
person ?. PersonAge
rather than
person ^. PersonAge
since PersonAge can be NULL, but changing it gives me a type error since:
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))
This is probably easier than I'm making it out to be, but I can't find examples anywhere online for using aggregate functions in Esqueleto, and I'm pretty new to Haskell so I'm having trouble figuring it out.
I suppose I could just use raw SQL, but if it's possible I'd like to do this using Esqueleto.