繁体   English   中英

如何使用Haskell的BSON模块捕获简单错误?

[英]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实例的重复吗?

如果你希望你lookEither情况下:

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.

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