Haskell 显示QuickCheck属性失败的原因并处理测试函数中的异常

Haskell 显示QuickCheck属性失败的原因并处理测试函数中的异常,haskell,quickcheck,Haskell,Quickcheck,我有一个快速检查属性测试函数f。属性将函数f映射到某个列表xs,并检查结果的某些元素属性。如果出现故障,我想显示与此故障相关的xs元素。考虑以下属性: prop x = printTestCase ("Failed for value " ++ show failure) $ isNothing failure where failure = fmap fst $ find (not . snd) $ map (\n -> (n, f x n == n)) [10..2

我有一个快速检查属性测试函数
f
。属性将函数
f
映射到某个列表
xs
,并检查结果的某些元素属性。如果出现故障,我想显示与此故障相关的
xs
元素。考虑以下属性:

prop x =
    printTestCase ("Failed for value " ++ show failure) $ isNothing failure
  where
    failure = fmap fst $ find (not . snd) $ map (\n -> (n, f x n == n)) [10..20]
这对实现非常有效

f = (+)
快速检查道具
输出

*** Failed! Falsifiable (after 2 tests):                  
1
Failed for value Just 10
*** Failed! Exception: 'Prelude.undefined' (after 1 test): 
()
Failed for value Exception thrown by generator: 'Prelude.undefined'
但是,如果
f
抛出异常,即

f = undefined
然后
quickcheck道具
输出

*** Failed! Falsifiable (after 2 tests):                  
1
Failed for value Just 10
*** Failed! Exception: 'Prelude.undefined' (after 1 test): 
()
Failed for value Exception thrown by generator: 'Prelude.undefined'
如何编写一个属性来捕获第二个异常并返回“仅0” 至于上一个例子?我想,可以使用
whenFail
whenFail'
来实现这一点,但我还没有理解QuickCheck的内部结构。

多亏了haskell频道上的aavogt,我找到了模块
Control.Spoon
,它提供了可以用来解决这个问题的函数Spoon和teaspoon。但是,我不知道使用这个包(它在内部使用
unsafePerformIO
)有多安全

无论如何,使用
Control.Spoon
prop
可以按以下方式重写:

prop x =
    printTestCase ("Failed for value " ++ show pureFailure) $ isNothing excFailure
  where
    pureFailure = failure (fromMaybe True . teaspoon)
    excFailure = failure id
    failure g = fmap fst $ find (g . not . snd) $ map (\n -> (n, f x n == n)) [10..20]
使用
fromTrue包装find谓词。茶匙
具有查找返回的效果 第一个元素要么满足谓词,要么引发异常

As
teaspoon
只能用于查看是否发生异常,但我使用的不是异常
excFailure
,这样QuickCheck仍然可以看到异常。不利的一面是这个发现 需要评估两次
teaspoon
仅计算WHNF,如果需要深入计算以触发异常,请使用
spoon


teaspoon
只捕获一些select异常,这对我来说很好,因为我只关心未定义和取之不尽的模式匹配。

为什么不为元素类型定义属性,让QuickCheck一次测试一个元素?然后QuickCheck会告诉你它失败的值。是的,我忘了提那个。在我的实际代码中,我通过在所有赋值的详尽列表中比较布尔公式来测试它们的等价性。输出应该给我第一个估值,这些公式与之不同。我改变了问题,给出了一个更接近我实际代码的示例。我仍然想知道是否有一个不使用unsafePerformIO的解决方案。