Как правильно сложить монады, чтобы наконец рендерить в 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
функция работает:
- + Изменить
txt <- renderTextT document
вtxt <- liftIO (renderTextT document)
- Попробуйте скомпилировать свой код, чтобы убедиться,
liftIO
импортируется (это, вероятно, уже). Если нет: добавитьimport Control.Monad.IO.Class
в ваш список импорта.