nvr*_*dow 1 haskell try-catch maybe
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables #-}
import Data.Typeable
import Control.Exception
data EmptyListException = EmptyListException
deriving (Show, Typeable)
instance Exception EmptyListException
myHead :: [a] -> a
myHead [] = throw EmptyListException
myHead (x:_) = x
mySafeHead :: [a] -> IO (Maybe a)
mySafeHead xs = (return (Just (myHead xs)))
`catch`
(\(ex::EmptyListException) -> return Nothing)
Run Code Online (Sandbox Code Playgroud)
我想返回xs的第一个元素,如果有的话.否则我想返回"Nothing",但它返回包含在"Just"中的Exception.这是为什么?PS:我必须使用myHead在mySaveHead.
所以当我运行你的代码时,这就是我所看到的
? mySafeHead []
Just *** Exception: EmptyListException
Run Code Online (Sandbox Code Playgroud)
我明白为什么你会把它描述为"它返回包含在"Just"中的Exception.",但这实际上不是正在发生的事情.
Haskell是非严格的,因此它推迟计算直到需要一个值.
在未检查mySafeHead的值中myHead xs,因此不进行评估.相反,该值的计算保留为thunk,它被包装Just并返回.
然后,在ghci尝试打印该值时,最终强制该thunk,并引发异常.由于我们现在已经超出了catch语句的范围,因此它不适用,并且异常使它一直到终端,它终止输出的打印.
解决这个问题的简单方法是在退出语句之前使用seq强制评估:myHead xscatch
mySafeHead' :: [a] -> IO (Maybe a)
mySafeHead' xs = (let x = myHead xs in x `seq` return (Just x))
`catch`
(\(_::EmptyListException) -> return Nothing)
Run Code Online (Sandbox Code Playgroud)
seq有两个参数 - 它返回第二个参数,但只有在强制第一个到弱头范式(WHNF)之后,也就是在找出最外面的构造函数之后.这有x足够的力量EmptyListException来提升,所以catch可以做到这一点:
? mySafeHead' []
Nothing
Run Code Online (Sandbox Code Playgroud)
您可以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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
781 次 |
| 最近记录: |