我想在这个类实例中的表达式中添加一个非常简单的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中使用try
和catch
,除非用作IO
操作,后者不能在纯代码中使用。然而,有一个简单的快速解决方案:
let locaPreds = filter (x -> Just x == fmap (agent -> verb agent predicate)
(getAgentByType x [HUMN]))
factsByArg
Maybe
是Functor
类型类的成员,这意味着它是许多数据类型之一,您可以使用fmap
将函数应用于它的"内部"。因此,您可以将检查推送到内部,而不是从Maybe
中取出。
如果getAgentByType x [HUMN]
的结果是Just agent
,那么函数将应用于agent
,得到结果Just (verb agent predicate)
,您可以将其与Just x
进行比较。如果有Nothing
,结果仍然是Nothing
,不等于Just x
,因此测试失败。
flip
函数允许您切换函数参数的顺序,因此您也可以将内部lambda表达式写为flip verb predicate
。