Blaze-html forM 块中的类型错误
Blaze-html type error inside forM_ block
我刚刚开始 Haskell 使用 Spock、persistent 和 blaze 进行 Web 开发-html。
在我的其中一条路线中,我想加载所选表格中的每一行。我这样做:
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
有类型:
Integer -> SqlPersistM [Entity Flight]
和 getSeatIdByFlight:
T.Text -> Integer -> SqlPersistM (Maybe (Entity Flight))
我从 Spock 的博客示例应用程序中复制了 runSQL
,它是这样的:
runSQL :: (HasSpock m, SpockConn m ~ SqlBackend) => SqlPersistT (NoLoggingT (ResourceT IO)) a -> m a
runSQL action = runQuery $ \conn -> runResourceT $ runNoLoggingT $ runSqlConn action conn
我得到的类型错误:
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
我还是不明白这个类型的错误,因为我知道runSQL
是persistent到Spock的包装器,如果我只是单纯的想输出HTML,为什么不能通过类型检查?
如何解决此类型错误?
免责声明:我没有运行你的代码。
I know runSQL
is a wrapper from persistent to Spock
没错,这就是你的问题。 runSQL
的类型是:
runSQL :: (HasSpock m, SpockConn m ~ SqlBackend)
=> SqlPersistT (NoLoggingT (ResourceT IO)) a -> m a
结果类型 (HasSpock m, SpockConn m ~ SqlBackend) => m a
告诉我们 runSQL
在 Spock monad 中给出了一个结果。因此,loadFlightSeat
也应该是一个 Spock monad 计算。但是,您给它的类型 H.Html
,这与 Spock monad 无关。如果您删除 loadFlightSeat
的错误类型签名并相应地调整 loadFlightSeat
的用法,该问题可能会消失:
flightSeat <- loadFlightSeat -- Returns an H.Html value in the Spock monad.
case fs of
[] -> blaze $ template False (showResultAlertBar False "Oops, something went wrong! Please try again.")
_ -> blaze $ template True (H.toHtml $ usersUsername l) flightSeat
P.S.: 你得到的类型错误...
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
...异常奇怪,因为 H.Html
happens to be a synonym for MarkupM ()
,MarkupM
是由 blaze
定义的单子。因此,您给 loadFlightSeat
的签名会导致编译器尝试将 Spock 的 monad 与 MarkupM
匹配。
我刚刚开始 Haskell 使用 Spock、persistent 和 blaze 进行 Web 开发-html。
在我的其中一条路线中,我想加载所选表格中的每一行。我这样做:
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
有类型:
Integer -> SqlPersistM [Entity Flight]
和 getSeatIdByFlight:
T.Text -> Integer -> SqlPersistM (Maybe (Entity Flight))
我从 Spock 的博客示例应用程序中复制了 runSQL
,它是这样的:
runSQL :: (HasSpock m, SpockConn m ~ SqlBackend) => SqlPersistT (NoLoggingT (ResourceT IO)) a -> m a
runSQL action = runQuery $ \conn -> runResourceT $ runNoLoggingT $ runSqlConn action conn
我得到的类型错误:
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
我还是不明白这个类型的错误,因为我知道runSQL
是persistent到Spock的包装器,如果我只是单纯的想输出HTML,为什么不能通过类型检查?
如何解决此类型错误?
免责声明:我没有运行你的代码。
I know
runSQL
is a wrapper from persistent to Spock
没错,这就是你的问题。 runSQL
的类型是:
runSQL :: (HasSpock m, SpockConn m ~ SqlBackend)
=> SqlPersistT (NoLoggingT (ResourceT IO)) a -> m a
结果类型 (HasSpock m, SpockConn m ~ SqlBackend) => m a
告诉我们 runSQL
在 Spock monad 中给出了一个结果。因此,loadFlightSeat
也应该是一个 Spock monad 计算。但是,您给它的类型 H.Html
,这与 Spock monad 无关。如果您删除 loadFlightSeat
的错误类型签名并相应地调整 loadFlightSeat
的用法,该问题可能会消失:
flightSeat <- loadFlightSeat -- Returns an H.Html value in the Spock monad.
case fs of
[] -> blaze $ template False (showResultAlertBar False "Oops, something went wrong! Please try again.")
_ -> blaze $ template True (H.toHtml $ usersUsername l) flightSeat
P.S.: 你得到的类型错误...
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
...异常奇怪,因为 H.Html
happens to be a synonym for MarkupM ()
,MarkupM
是由 blaze
定义的单子。因此,您给 loadFlightSeat
的签名会导致编译器尝试将 Spock 的 monad 与 MarkupM
匹配。