所以当我运行你的代码时,这就是我所看到的
? mySafeHead [] Just *** Exception: EmptyListException
我明白为什么你会把它描述为"它返回包含在"Just"中的Exception.",但这实际上不是正在发生的事情.
Haskell是非严格的,因此它推迟计算直到需要一个值.
在未检查mySafeHead
的值中myHead xs
,因此不进行评估.相反,该值的计算保留为thunk,它被包装Just
并返回.
然后,在ghci
尝试打印该值时,最终强制该thunk,并引发异常.由于我们现在已经超出了catch
语句的范围,因此它不适用,并且异常使它一直到终端,它终止输出的打印.
解决这个问题的简单方法是在退出语句之前使用seq
强制评估:myHead xs
catch
mySafeHead' :: [a] -> IO (Maybe a) mySafeHead' xs = (let x = myHead xs in x `seq` return (Just x)) `catch` (\(_::EmptyListException) -> return Nothing)
seq
有两个参数 - 它返回第二个参数,但只有在强制第一个到弱头范式(WHNF)之后,也就是在找出最外面的构造函数之后.这有x
足够的力量EmptyListException
来提升,所以catch
可以做到这一点:
? mySafeHead' [] Nothing
Shoe.. 5
您可以evaluate
在执行纯计算时用于捕获异常:
mySafeHead :: [a] -> IO (Maybe a) mySafeHead xs = mySafeHead' xs `catch` handler where mySafeHead' :: [a] -> IO (Maybe a) mySafeHead' ls = do x <- evaluate $ myHead ls return $ Just x handler :: EmptyListException -> IO (Maybe a) handler ex = return Nothing
Live demo
所以当我运行你的代码时,这就是我所看到的
? mySafeHead [] Just *** Exception: EmptyListException
我明白为什么你会把它描述为"它返回包含在"Just"中的Exception.",但这实际上不是正在发生的事情.
Haskell是非严格的,因此它推迟计算直到需要一个值.
在未检查mySafeHead
的值中myHead xs
,因此不进行评估.相反,该值的计算保留为thunk,它被包装Just
并返回.
然后,在ghci
尝试打印该值时,最终强制该thunk,并引发异常.由于我们现在已经超出了catch
语句的范围,因此它不适用,并且异常使它一直到终端,它终止输出的打印.
解决这个问题的简单方法是在退出语句之前使用seq
强制评估:myHead xs
catch
mySafeHead' :: [a] -> IO (Maybe a) mySafeHead' xs = (let x = myHead xs in x `seq` return (Just x)) `catch` (\(_::EmptyListException) -> return Nothing)
seq
有两个参数 - 它返回第二个参数,但只有在强制第一个到弱头范式(WHNF)之后,也就是在找出最外面的构造函数之后.这有x
足够的力量EmptyListException
来提升,所以catch
可以做到这一点:
? mySafeHead' [] Nothing
您可以evaluate
在执行纯计算时用于捕获异常:
mySafeHead :: [a] -> IO (Maybe a) mySafeHead xs = mySafeHead' xs `catch` handler where mySafeHead' :: [a] -> IO (Maybe a) mySafeHead' ls = do x <- evaluate $ myHead ls return $ Just x handler :: EmptyListException -> IO (Maybe a) handler ex = return Nothing
Live demo