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

时间:2012-11-25 21:11:06

标签: haskell bson

我有一组Data.BSON.Document结构,我正在挖掘,将每个结构转换为用户数据结构(我定义了用户)。解包的功能非常简单:

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
但是,问题是它在Either上下文中实际上似乎没有错误。以下是一些示例运行:

*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数据结构中的错误?

3 个答案:

答案 0 :(得分:2)

look通过monadic 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"

答案 1 :(得分:1)

基于我可以从herehere以及其他一般Google搜索中找到的信息...... Either monad的实例不会拥有 a {{ 1}}实施。猜测一下,这就是为什么我得到一个异常而不是Left。我写了这个小测试来证明:

fail

另一方面,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" 确实没有返回任何内容。看起来我的docToUser转换的正确方法更类似于:

fail :: String -> Maybe String

我认为这可以进行相当多的改进,特别是在检测和报告哪些字段失败时。但是,这似乎非常接近答案。

我认为,鉴于此,这个问题与Is there no standard (Either a) monad instance?

重复

答案 2 :(得分:0)

如果您想在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)