Как правильно сложить монады, чтобы наконец рендерить в html?

Моя цель - правильно передать html-функцию (как определено в Spock-core) с типом HtmlT m (в идеале Html ()). Между ними я выполняю некоторые запросы Network.Http.Simple. По-видимому, мои знания о Хаскеле недостаточны, я не нашел способ заставить правильную монаду. Насколько я знаю (и понимаю весь смысл монад), нет никакого способа составить разные монады, например (Монада М, Монада N => M a -> (a -> N b) -> N b) .

лучшее, чего мне удалось добиться, - это настроить тип HtmlT IO (), но затем я застрял в функции преобразования. lucid :: HtmlT IO () -> SpockAction dtb sess state ()

вот моя функция соединения (Auth - структура данных FromJSON для размещения ключа авторизации и токена)

     connect :: IO Auth
     connect = do  
                ...building a http request.. 
                response <- httpJSON request
                return (getResponseBody response :: Auth)

Затем это подключиться в функции getRequest типа String -> HtmlT IO ()

    getRequest :: RequestPath -> HtmlT IO ()
    getRequest rpath = do
                    atoken <- liftIO connect
                    request' <- liftIO parseRequest "http://......"
                    let request = { series of set methods
                                    to build the request }
                    response <- httpLBS request
                    liftIO (L8.putStrnLn $ (getResponseBody response))

и вот мы подошли к ясной функции, Lucid может обрабатывать преобразования Html () -> SpockAction ... Html () - это не что иное, как HtmlT Identity (), поэтому моя первая попытка заключалась в том, чтобы кормить lcid с помощью HtmlT IO ()

   lucid :: HtmlT IO () -> SpockAction database session state ()
   lucid document = do 
                        txt <- renderTextT document       --> inside IO (?)
                        return html (TL.toStrict txt)     <-- naive attempt to 
                                      return to "somewhere" of course stupid..

Может быть, IO не хорошая монада здесь? Когда я пытаюсь использовать монаду Identity (чтобы иметь HtmlT Identity ()), поэтому, если я определяю connect как connect:: Identity Auth, то, естественно, следует, что меня спрашивают об экземпляре FromJSON Identity (возникающем при использовании httpJSON), возможно, это потенциальное решение, как только я нахожусь в монаде Identity, я могу соединить вещи и, вероятно, закончить с чистым типом Html (), который затем будет плавно выполняться моей lucid-функцией.

Спасибо за любую подсказку или подсказки, может быть, мой подход совершенно неверен, и все, над чем я работаю, - это запросить сайт restAPI и посмотреть результат на веб-сервере, работающем со Spock.

1 ответ

Соответствующие типы:

document :: HtmlT IO ()
renderTextT :: Monad m => HtmlT m a -> m Text
renderTextT document :: IO Text
<the value you need> :: SpockAction database session state Text

К счастью, у нас есть это в наличии: liftIO :: MonadIO m => IO a -> m a

Два шага к получению lucid функция работает:

  1. + Изменить txt <- renderTextT document в txt <- liftIO (renderTextT document)
  2. Попробуйте скомпилировать свой код, чтобы убедиться, liftIO импортируется (это, вероятно, уже). Если нет: добавить import Control.Monad.IO.Class в ваш список импорта.
Другие вопросы по тегам