Haskell新手在这里。我正在尝试使用http-enumerator通过HTTP上的XML查询服务。我能够连接并发送xml格式的请求,并接收xml格式的响应。
查询成功后,服务器会发回一个响应
我正在努力解决的是处理FAULT文档中指出的异常的正确方法。我正在尝试使用Either
,但没有成功。
我在下面的内容中编译ghci:
import Network.HTTP.Enumerator
import Network.HTTP.Types
import qualified Data.ByteString.Lazy as L
import Data.ByteString.UTF8
import Text.XML.Light
hostname = "https://server..."
doPost username password token = do
let q = QName "SYSTEM" Nothing Nothing
let attribs = [Attr {attrKey = QName "user" Nothing Nothing, attrVal = username},
Attr {attrKey = QName "password" Nothing Nothing, attrVal = password},
Attr {attrKey = QName "token" Nothing Nothing, attrVal = token}]
let doc = Element {elName=q, elAttribs=attribs, elContent= [], elLine=Nothing}
req0 <- parseUrl hostname
let req = req0 { method = methodPost
, requestHeaders = [("Content-Type", "text/xml")]
, requestBody = RequestBodyBS $ fromString $ showTopElement doc
}
res <- withManager $ httpLbs req
let status = Network.HTTP.Enumerator.statusCode res
let content = responseBody res
-- this is where I would check for different fault codes using a case statement
if content == "<FAULT/>"
then Left "error"
else Right content
然而,当我尝试在ghci中运行它时,我得到以下内容:
*Main> doPost "user" "password" ""
<interactive>:1:1:
No instances for (Control.Failure.Failure
HttpException (Either a0),
Control.Monad.IO.Control.MonadControlIO (Either a0))
arising from a use of `doPost'
Possible fix:
add instance declarations for
(Control.Failure.Failure HttpException (Either a0),
Control.Monad.IO.Control.MonadControlIO (Either a0))
In the expression: doPost "user" "password" ""
In an equation for `it': it = doPost "user" "password" ""
在这种情况下处理异常的最佳方法是什么?
提前致谢。 尼尔
答案 0 :(得分:6)
您需要在最后一个if之前加上“return $”。 parseUrl需要在monad中运行,monad是Failure HttpException
的实例,例如IO或Maybe。 withManager
需要一个MonadControlIO
实例的monad,例如IO
。
目前,您最后的if
强制整个do
- 块在Either String
monad中运行,这就是您获得“无实例”异常的原因。如果您添加退货,则最终结果将类似于IO (Either String XML)
。