简体   繁体   English

如何正确堆叠monad以最终呈现为html?

[英]How to stack correctly monads to finally render to html?

My goal is to feed correctly the html function (as define in Spock-core) with a HtmlT m type (ideally Html () ). 我的目标是使用HtmlT m类型(最好是Html () )正确地馈送html函数(在Spock-core中定义)。 In between I am performing some Network.Http.Simple requests. 在这之间,我正在执行一些Network.Http.Simple请求。 Apparently my knowledge of Haskell is insufficient, I didn't find the way to force the correct monad. 显然我对Haskell的了解不足,我没有找到强制正确的monad的方法。 As far as I know (and understand the whole sense of monads) there is no way to compose different monads something like (Monad M, Monad N => M a -> (a -> N b) -> N b) . 据我所知(并理解单子的整体含义),没有办法组成不同的单子,例如(Monad M, Monad N => M a -> (a -> N b) -> N b)

The best I manage to achieve was to set up a HtmlT IO () type but then I get stuck in the conversion function lucid :: HtmlT IO () -> SpockAction dtb sess state () 我设法达到的最佳效果是设置HtmlT IO ()类型,但随后陷入转换函数lucid :: HtmlT IO () -> SpockAction dtb sess state ()

Here is my connection function ( Auth is a FromJSON data structure to host authorization key and token) 这是我的连接函数( Auth是用于承载授权密钥和令牌的FromJSON数据结构)

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

Next this get wired in a getRequest function of type String -> HtmlT IO () 接下来,将其getRequest到类型为String -> HtmlT IO ()getRequest函数中

    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))

and here we come to the lucid function, Lucid can handle transformation Html () -> SpockAction ... . 在这里我们介绍了lucid函数,Lucid可以处理Html () -> SpockAction ... Html () is nothing else than HtmlT Identity () so my first attempt was to feed lucid with HtmlT IO () . Html ()就是HtmlT Identity ()所以我的第一个尝试是用HtmlT IO ()来提供清醒的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..

Maybe IO is not the good monad here? IO可能不是这里的好单子吗? When I try the Identity monad (to have a HtmlT Identity () ) so if I define connect as connect :: Identity Auth then naturally it follows that I am asked for a FromJSON instance of Identity (arising from using httpJSON), maybe that's a potential solution once I am in the Identity monad I am able to wire things up and probably finish with a clean Html () type which will be then executed smoothly by my lucid function. 当我尝试使用Identity monad(具有HtmlT Identity () )时,如果我将connect定义为connect :: Identity Auth那么很自然地,我会被要求输入Identity的FromJSON实例(使用httpJSON引起),也许是潜在的解决方案一旦我进入Identity monad,就可以进行连接,并可能以干净的Html ()类型结束,然后由我的清醒函数平稳地执行它。

Thank you for any clue or hints, maybe my approach is totally wrong the whole thing I am working on is to query a restAPI website and view the result on a web server run with Spock. 感谢您提供的任何线索或提示,也许我的方法是完全错误的,整个工作是查询restAPI网站并在使用Spock运行的Web服务器上查看结果。

The relevant types: 相关类型:

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

Fortunately we have this available: liftIO :: MonadIO m => IO a -> ma 幸运的是,我们有以下可用: liftIO :: MonadIO m => IO a -> ma

Two steps to getting your lucid function running: 运行lucid函数的两个步骤:

  1. Change txt <- renderTextT document to txt <- liftIO (renderTextT document) txt <- renderTextT document更改为txt <- liftIO (renderTextT document)
  2. Try to compile your code to make sure liftIO is imported (it probably is already). 尝试编译您的代码以确保liftIO已导入(可能已经导入)。 If not: add import Control.Monad.IO.Class to your import list. 如果不是这样:将import Control.Monad.IO.Class添加到您的导入列表。
  3. Remove the return from return html (TL.toStrict txt) . return html (TL.toStrict txt)删除return

The following code is working on my machine: 以下代码在我的计算机上运行:

lucid :: HtmlT IO () -> SpockAction database session state ()
lucid document = do
  txt <- liftIO (renderTextT document)
  html (TL.toStrict txt)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM