I'm trying to extend Happstack crash course blog with some additional functionality: displaying a list of all tags on home page.
My blog record looks like this:
data Blog = Blog
{ nextPostId :: PostId
, posts :: IxSet Post
, allTags :: [Text]
}
deriving (Data, Typeable)
I get blog post by id in the following way (copypasted from crash course):
-- Models.hs
postById :: PostId -> Query Blog (Maybe Post)
postById pid =
do Blog{..} <- ask
return $ getOne $ posts @= pid
-- Controller.hs
viewPage :: AcidState Blog -> ServerPart Response
viewPage acid =
do pid <- PostId <$> lookRead "id"
mPost <- query' acid (PostById pid)
...
-- mPost has type Maybe Post here
...
And it works alright.
When I try to do querying of all tags in the similar way:
-- Models.hs
getTags :: Query Blog [Text]
getTags =
do Blog{..} <- ask
return allTags
-- Controller.hs
serveTags :: AcidState Blog -> [Text]
serveTags acid = query' acid GetTags
It won't work. The error stack trace is:
Blog/Controllers.hs:154:18:
Couldn't match type `[Text]' with `Text'
Expected type: [Text]
Actual type: [acid-state-0.8.1:Data.Acid.Common.EventResult
GetTags]
In the return type of a call of query'
In the expression: query' acid GetTags
I can't figure out why the return type of query'
is [EventResult GetTags]
, while it should be [Text]
.
What is the reason for this error? Is there a way to fix it?
The problem is your type signature on the serveTags
function, it should be monadic:
serveTags :: MonadIO m => AcidState Blog -> m [Text]
serveTags acid = query' acid GetTags
EventResult
is a type family that here resolves to [Text]
. Since query'
is monadic, your type signature got resolved to the list monad, i.e. m Text
where the m
is the list monad, thus the confusing error message.