【发布时间】:2011-04-17 23:23:49
【问题描述】:
我在一个模块中有一个看起来像这样的函数:
module MyLibrary (throwIfNegative) where
throwIfNegative :: Integral i => i -> String
throwIfNegative n | n < 0 = error "negative"
| otherwise = "no worries"
我当然可以返回Maybe String 或其他一些变体,但我认为使用负数调用此函数是程序员的错误,因此在这里使用error 是合理的。
现在,因为我喜欢 100% 的测试覆盖率,所以我想要一个测试用例来检查这种行为。这个我试过了
import Control.Exception
import Test.HUnit
import MyLibrary
case_negative =
handleJust errorCalls (const $ return ()) $ do
evaluate $ throwIfNegative (-1)
assertFailure "must throw when given a negative number"
where errorCalls (ErrorCall _) = Just ()
main = runTestTT $ TestCase case_negative
它有点工作,但在使用优化编译时失败:
$ ghc --make -O Test.hs
$ ./Test
### Failure:
must throw when given a negative number
Cases: 1 Tried: 1 Errors: 0 Failures: 1
我不确定这里发生了什么。似乎尽管我使用了evaluate,但该函数并未得到评估。此外,如果我执行以下任何步骤,它会再次起作用:
- 去掉HUnit,直接调用代码
- 将
throwIfNegative移动到与测试用例相同的模块中 - 删除
throwIfNegative的类型签名
我认为这是因为它会导致应用不同的优化。有什么指点吗?
【问题讨论】:
-
我可以重现这个。有趣的!此外,如果您在模块中包含
throwIfNegative,并标有NOINLINE,则会失败。
标签: exception optimization haskell ghc hunit