Sve*_*mir 3 haskell exception-handling strict
在Haskell中做一些TTD时,我最近开发了以下功能:
import Test.HUnit
import Data.Typeable
import Control.Exception
assertException :: (Show a) => TypeRep -> IO a -> Assertion
assertException errType fun = catch (fun >> assertFailure msg) handle
where
msg = show errType ++ " exception was not raised!"
handle (SomeException e) [...]
Run Code Online (Sandbox Code Playgroud)
该函数采用Type表示预期异常和IO操作.问题是,大部分时间我都没有抛出异常,即使我本来应该抛弃,因为懒惰.通常,失败的部分fun实际上从未在此进行过评估.
为了解决这个问题,我试图(fun >> assertFailure msg)用(seq fun $ assertFailure msg).我还尝试启用BangPatterns扩展并在fun绑定之前发出爆炸声,但没有一个帮助.那么我怎么能真正强迫Haskell fun严格评估呢?
你必须区分:
IO aa,和a(或部分)的结果.这些总是按顺序发生,但不一定全部发生.代码
foo1 :: IO a -> IO ()
foo1 f = do
seq f (putStrLn "done")
Run Code Online (Sandbox Code Playgroud)
只做第一次,而
foo2 :: IO a -> IO ()
foo2 f = do
f -- equivalent to _ <- f
putStrLn "done"
Run Code Online (Sandbox Code Playgroud)
第二次也是最后一次
foo3 :: IO a -> IO ()
foo3 f = do
x <- f
seq x $ putStrLn "done"
Run Code Online (Sandbox Code Playgroud)
也是第三个(但是在seq列表等复杂数据类型上使用的常用注意事项).
尝试这些参数并观察它foo1,foo2并foo3以不同的方式对待它们.
f1 = error "I am not a value"
f2 = fix id -- neither am I
f3 = do {putStrLn "Something is printed"; return 42}
f4 = do {putStrLn "Something is printed"; return (error "x has been evaluated")}
f5 = do {putStrLn "Something is printed"; return (Just (error "x has been deeply evaluated"))}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
129 次 |
| 最近记录: |