在Haskell中插入一行try-catch块



我想在这个类实例中的表达式中添加一个非常简单的try-catch块,它没有刺激,以便处理返回Nothing的情况。

instance QWho (Argument -> Predicate -> Predicate) Predicate where
            qWho verb predicate =
                let 
                arg = head (arguments predicate)
                factsByArg = getFactsByArg arg
                in if null factsByArg then error ("The argument <" ++ getValue arg ++ "> does not exist in any fact.") 
                else
                    let locaPreds = filter (x -> x == (verb (fromJust (getAgentByType x [HUMN])) predicate)) factsByArg
                    in if null locaPreds then error ("No such fact exists.")
                    else
                        let locaArgs = map (x -> getAgent x) locaPreds
                        in map getValue locaArgs

有问题的表达式是(x -> x == (verb (fromJust (getAgentByType x [HUMN])) predicate))。这是有效的,除非fromJust返回Nothing。理想情况下,我想我可以做这样的事情:

(x -> try (x == (verb (fromJust (getAgentByType x [HUMN]))))

但这不起作用(在Java这样的语言中会起作用,尽管最后我需要一个陷阱。)

有很多资源试图解释如何在Haskell中执行try-catch块。我发现的那些并没有提供我想要的任何快速修复(即没有对代码进行重大重组)。有没有一个快速的解决方案可以忽略返回Nothing的情况,而不是让程序因Maybe.fromJust异常而退出?

相关来源:

(1)http://drunkcoding.tumblr.com/post/692076953/catching-exceptions-in-haskell

您不能在Haskell中使用trycatch,除非用作IO操作,后者不能在纯代码中使用。然而,一个简单的快速解决方案:

let locaPreds = filter (x -> Just x == fmap (agent -> verb agent predicate)
                                             (getAgentByType x [HUMN]))
                    factsByArg

MaybeFunctor类型类的成员,这意味着它是许多数据类型之一,您可以使用fmap将函数应用于它的"内部"。因此,您可以将检查推送到内部,而不是从Maybe中取出

如果getAgentByType x [HUMN]的结果是Just agent,那么函数将应用于agent,得到结果Just (verb agent predicate),您可以将其与Just x进行比较。如果有Nothing,结果仍然是Nothing,不等于Just x,因此测试失败。

flip函数允许您切换函数参数的顺序,因此您也可以将内部lambda表达式写为flip verb predicate

最新更新