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
runSQLis:The result type,
(HasSpock m, SpockConn m ~ SqlBackend) => m a, tells us thatrunSQLgives a result in the Spock monad. Therefore,loadFlightSeatshould 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 ofloadFlightSeatand adjust your usage ofloadFlightSeataccordingly:P.S.: The type error you got...
...is unusually weird because
H.Htmlhappens to be a synonym forMarkupM (), withMarkupMbeing a monad defined byblaze. As a consequence, the signature you gave toloadFlightSeatleads the compiler to attempt matching Spock's monad withMarkupM.