我的目标是用HtmlT m
类型(理想情况下Html ()
)正确输入html函数(如Spock-core中所定义)。在这两者之间,我正在执行一些Network.Http.Simple请求。显然我对Haskell的了解不足,我没有找到强制正确monad的方法。据我所知(并理解 monads 的整个含义),没有办法像(Monad M, Monad N => M a -> (a -> N b) -> N b)
这样组成不同的 monads .
我设法实现的最好结果是设置一个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)
接下来,这将连接到类型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))
这里我们来到 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
不是这里的好单子?当我尝试使用身份monad(有一个HtmlT Identity ()
)时,所以如果我将连接定义为connect :: Identity Auth
那么自然而然地,我被要求提供身份的FromJSON实例(由使用httpJSON产生),也许这是一个潜在的解决方案,一旦我进入身份monad,我就能够连接起来,并可能以一个干净的Html ()
类型完成,然后由我的清晰函数顺利执行。
感谢您提供任何线索或提示,也许我的方法完全错误,我正在做的整个事情是查询 restAPI 网站并在使用 Spock 运行的 Web 服务器上查看结果。
相关类型:
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
添加到导入列表中。 - 从
return html (TL.toStrict txt)
中删除return
。
以下代码正在我的机器上运行:
lucid :: HtmlT IO () -> SpockAction database session state ()
lucid document = do
txt <- liftIO (renderTextT document)
html (TL.toStrict txt)