I'm just starting Haskell web development using Spock, persistent and blaze-html.
In one of the routes I have, I want to load every row in my selected tables. I do something like this:
get ("/show/flight/" <//> (var :: Var Integer)) $ \f -> requireUser $ \(_, l) -> do
fs <- runSQL $ loadFlightInfos f
case fs of
[] -> blaze $ template False (showResultAlertBar False "Oops, something went wrong! Please try again.")
_ -> blaze $ template True (H.toHtml $ usersUsername l) loadFlightSeat
where
loadFlightSeat :: H.Html
loadFlightSeat =
forM_ fs $ \fs' -> do
sid <- runSQL $ getSeatIdByFlight fs' c
case sid of
Nothing -> H.div H.! A.class_ "alert alert-danger" $ "Oops, something went wrong! Please try again."
Just rid -> H.a H.! A.href (H.toValue $ "/flight/seat/" <> show c <> "/" <> show (fromIntegral $ (fromSqlKey . entityKey) sid)) H.! A.class_ "btn btn-theme" $ H.toHtml fs'
loadFlightInfos
has type:
Integer -> SqlPersistM [Entity Flight]
and getSeatIdByFlight:
T.Text -> Integer -> SqlPersistM (Maybe (Entity Flight))
I copied runSQL
from Spock's blog sample app, and it's something like this:
runSQL :: (HasSpock m, SpockConn m ~ SqlBackend) => SqlPersistT (NoLoggingT (ResourceT IO)) a -> m a
runSQL action = runQuery $ \conn -> runResourceT $ runNoLoggingT $ runSqlConn action conn
The type error I got:
Couldn't match expected type ‘SqlBackend’
with actual type ‘SpockConn Text.Blaze.Internal.MarkupM’
In the expression: runSQL
In a stmt of a 'do' block:
sid <- runSQL $ getSeatIdByFlight fs' c
I still don't understand this type error, because I know runSQL
is a wrapper from persistent to Spock and if I simply just want to output HTML, why can't it pass type checking?
How do I resolve this type error?
Disclaimer: I didn't run your code.
Exactly, and there lies your issue. The type of
runSQL
is:The result type,
(HasSpock m, SpockConn m ~ SqlBackend) => m a
, tells us thatrunSQL
gives a result in the Spock monad. Therefore,loadFlightSeat
should be a Spock monad computation as well. However, you gave it typeH.Html
, which has nothing to do with the Spock monad. The issue will probably go away if you remove the mistaken type signature ofloadFlightSeat
and adjust your usage ofloadFlightSeat
accordingly:P.S.: The type error you got...
...is unusually weird because
H.Html
happens to be a synonym forMarkupM ()
, withMarkupM
being a monad defined byblaze
. As a consequence, the signature you gave toloadFlightSeat
leads the compiler to attempt matching Spock's monad withMarkupM
.