Как правильно сложить монады, чтобы наконец рендерить в html? - PullRequest
1 голос
/ 30 мая 2019

Моя цель - правильно передать html-функцию (как определено в Spock-core) с типом HtmlT m (в идеале Html ()).Между ними я выполняю некоторые запросы Network.Http.Simple.По-видимому, мои знания о Хаскеле недостаточны, я не нашел способ заставить правильную монаду.Насколько я знаю (и понимаю весь смысл монад), нет никакого способа составить разные монады, например, (Monad M, Monad 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, Lucid может обрабатывать преобразование Html () -> SpockAction ....Html () - это не что иное, как HtmlT Identity (), поэтому моей первой попыткой было кормить Люцида с помощью 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 (), который затем будет плавно выполняться моей ясной функцией.

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

1 Ответ

0 голосов
/ 31 мая 2019

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

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 в свой список импорта.
  3. Удалить return из return html (TL.toStrict txt).

На моей машине работает следующий код:

lucid :: HtmlT IO () -> SpockAction database session state ()
lucid document = do
  txt <- liftIO (renderTextT document)
  html (TL.toStrict txt)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...