Exception 在Haskell中插入一行try catch块

Exception 在Haskell中插入一行try catch块,exception,haskell,exception-handling,try-catch,Exception,Haskell,Exception Handling,Try Catch,我想在这个类实例中的表达式中添加一个非常简单的try-catch块,它没有刺激,以便处理返回Nothing的情况 instance QWho (Argument -> Predicate -> Predicate) Predicate where qWho verb predicate = let arg = head (arguments predicate)

我想在这个类实例中的表达式中添加一个非常简单的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
但这是行不通的(这在Java这样的语言中是行不通的,不过我需要在最后做个总结。)

有很多参考资料试图解释如何在Haskell中执行try-catch块。我发现的那些没有提供一个我正在寻找的快速修复(即没有对代码进行重大重组)。是否有一种快速修复方法可以忽略返回
Nothing
的情况,而不是让程序因为
Maybe.fromJust
异常而退出

有关资料来源:


(1)

您不能在Haskell中使用
try
catch
,除非作为
IO
操作,不能在纯代码中使用。但是,有一个简单的快速修复方法:

let locaPreds = filter (\x -> Just x == fmap (\agent -> verb agent predicate)
                                             (getAgentByType x [HUMN]))
                    factsByArg
可能
Functor
类型类的成员,这意味着它是可以使用
fmap
将函数应用于其“内部”的许多数据类型之一。因此,您可以将支票推到里面,而不是从
Maybe
中取出东西

如果
getagentbytypex[HUMN]
的结果是
Just-agent
,那么该函数将应用于
agent
,给出结果
Just(动词-代理谓词)
,您可以将其与
Just-x
进行比较。 如果存在一个
Nothing
,结果仍然是
Nothing
,这不等于
仅x
,因此测试失败


flip
函数允许您切换函数参数的顺序,因此您也可以将内部lambda表达式缩短为
flip谓词

为什么不在使用
fromJust
之前检查
是否为Nothing…
?或者更好的是,使用模式匹配和
case
来处理
Nothing
Just x
两种情况?
fromJust
partial函数可以说是破坏/消除
可能是
值的最糟糕方法。TLDR:不要寻找处理异常的方法,而是避免它!确保您的
然后
/
否则
缩进的距离比相应的
如果
缩进的距离远。当
let
语句比
let
语句缩进得更远时,它的内容在我看来更好看,但那只是一种风格。我不确定如何将case语句放入lambda表达式中。查看此线程:@genisage是否有一种方法可以对所有作用域使用parens,例如在Lisp中?我使用的编辑器实际上不能处理缩进。
case…
只是一个表达式,您可以将其放入lambda表达式中,尽管它确实在其中创建了一个缩进块。Haskell在编辑器中没有缩进听起来很痛苦。但是你。
let locaPreds = filter (\x -> Just x == fmap (\agent -> verb agent predicate)
                                             (getAgentByType x [HUMN]))
                    factsByArg