Ошибка типа Blaze-html внутри блока forM_

Я только начинаю веб-разработку на Haskell, используя Spock, persistent и blaze-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))

Я скопировал 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 такое обёртка от персистента до Спока и если я просто хочу вывести HTML, почему он не может пройти проверку типов?

Как мне решить эту ошибку типа?

1 ответ

Решение

Отказ от ответственности: я не запускал ваш код.

я знаю runSQL это обертка от персоны к споку

Именно так и кроется ваша проблема. Тип runSQL является:

runSQL :: (HasSpock m, SpockConn m ~ SqlBackend)
       => SqlPersistT (NoLoggingT (ResourceT IO)) a -> m a

Тип результата, (HasSpock m, SpockConn m ~ SqlBackend) => m aговорит нам, что runSQL дает результат в монаде Спока. Следовательно, loadFlightSeat должно быть вычисление монады Спока, а также. Тем не менее, вы дали ему тип H.Html, который не имеет ничего общего с монадой Спока. Проблема, вероятно, исчезнет, ​​если вы удалите ошибочную подпись типа 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

PS: ошибка типа вы получили...

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 случается, синонимMarkupM (), с MarkupM будучи монадой, определяемой blaze, Как следствие, подпись, которую вы дали loadFlightSeat приводит компилятор к попытке сопоставить монаду Спока с MarkupM,

Другие вопросы по тегам