[英]How do I catch simple errors with Haskell's BSON module?
我正在挖掘一组Data.BSON.Document结构,将每个结构都转换为User数据结构(我定义了User)。 进行拆包的功能非常简单:
docToUser :: Document -> Either String User
docToUser u = do
name <- look "name" u >>= \(String t) -> return $ unpack t
email <- look "email" u >>= \(String t) -> return $ unpack t
token <- look "auth" u >>= \(String t) -> return $ unpack t
Right $ User name email token
不过,要注意的是,在任何一种情况下它似乎都没有出错。 这是一些示例运行:
*DB> docToUser ["name" =: "Savanni", "email" =: "savanni@nowhere.com", "auth" =: "random_token"]
Right (User {name = "Savanni", email = "savanni@nowhere.com", token = "random_token"})
*DB> docToUser ["name" =: "Savanni", "email" =: "savanni@nowhere.com", "a" =: "random_token"]
*** Exception: expected "auth" in [ name: "Savanni", email: "savanni@nowhere.com", a: "random_token"]
因此,第一次运行将返回包装在Right
构造函数中的用户。 第二个是我期望的东西,例如Left "field not found"
,但是得到了一个完整的例外。 为什么会发生这种情况,而不是在Either数据结构中存储错误?
look
指示整个单例fail
原语中“未找到”。 您的返回类型为Either
的事实是无关紧要的。 您不能在do
表达式中处理此失败; 您必须编写如下内容:
unpackUser u = case (look "name" u, look "email" u, look "auth") of
(Just (String name), Just (String email), Just (String token)) -> Right $ User (unpack name) (unpack email) (unpack token)
_ -> Left $ "Missing required fields"
在此基础上,我可以从查找资料在这里 , 在这里 ,和其他一般周围的Googling ......对于无论是单子的实例没有一个fail
的实现。 猜测,这就是为什么我得到异常而不是Left的原因。 我写了这个小测试来演示:
eitherMonad :: String -> Either String String
eitherMonad val = do
if val == "abcd"
then fail "val is abcd"
else return "val is something else"
*DB> eitherMonad "abcd"
*** Exception: val is abcd
*DB> eitherMonad "efgh"
Right "val is something else"
另一方面, fail :: String -> Maybe String
确实返回Nothing。 看来,完成docToUser转换的正确方法与此类似:
docToUser :: Document -> Either String User
docToUser u = do
let name = look "name" u :: Maybe Value
let email = look "email" u :: Maybe Value
let token = look "auth" u :: Maybe Value
case (name, email, token) of
(Just (String n), Just (String e), Just (String t)) -> Right $ User (unpack n) (unpack e) (unpack t)
(Nothing, _, _) -> Left "username not found"
(Just (String n), Nothing, _) -> Left "email not found"
(Just (String n), Just (String e), Nothing) -> Left "auth token not found"
otherwise -> Left "Something else broke"
我想这可能需要很多改进,尤其是在检测和报告哪些字段失败的情况下。 但是,这似乎很接近答案。
鉴于此,我认为这个问题是没有标准(无论是一个)monad实例的重复吗?
如果你希望你look
在Either
情况下:
docToUser = do
String name <- look "name" u
String email <- look "email" u
String token <- look "token" u
return $ User (unpack name) (unpack email) (unpack token)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.