Haskell 如何使用断言?

Haskell 如何使用断言?,haskell,Haskell,我很难理解如何使用assert函数(Control.Exception.assert) 我确实阅读了文档(),但我似乎仍然不明白它是如何使用的。在这种情况下,咖喱真的没有帮助,因为它是多么的不可解释。举例说明它的用途会很好 (在上下文中,我试图弄清楚如何在代码中使用assert来确保n始终是非负的)[请不要回答,我想自己弄清楚] power :: Int -> Int -> Int power x n = if n == 0 then 1 else x * p

我很难理解如何使用assert函数(Control.Exception.assert)

我确实阅读了文档(),但我似乎仍然不明白它是如何使用的。在这种情况下,咖喱真的没有帮助,因为它是多么的不可解释。举例说明它的用途会很好

(在上下文中,我试图弄清楚如何在代码中使用assert来确保n始终是非负的)[请不要回答,我想自己弄清楚]

power :: Int -> Int -> Int
power x n =
  if n == 0 then
    1
  else
    x * power x (n - 1)

assert
视为一个条件标识函数。如果第一个参数为false,则引发异常。否则,将返回第二个参数。实现可能类似于

assert :: Bool -> a -> a
assert True = id
assert False = \_ -> error "Assertion Failed"  -- const (error "Assertion Failed")

(我不确定使用它的哪个示例不会有效地泄露如何编写
power

从该库导出的
assert
(我没有使用过)实际上是在
base
中定义的。您可以这样使用它:

power :: Int -> Int -> Int
power x n = assert (n >= 0) $
  if n == 0 then
    1
  else
    x * power x (n - 1)
但这并不是函数的真正目的。在上述情况下,最好用友好的消息引发您自己的错误,或者(更好的是)返回一个
可能是Int

assert
用于检查函数中的内部不变量,如果出现冲突则表示存在错误。将断言与测试结合使用(测试执行由内部
assert
调用检查的不变量)非常有用

您必须确保编译时不使用优化或使用
-fno ignore asserts
,因为使用优化编译时会优化断言(assert
的另一个重要功能)

我在库代码中包含了以下内容,以便在我的测试套件中进行断言测试(非常重要,我以前遇到过这个问题):

assertionCanary::IO Bool
assertionCanary=do
断言是正确的
_->错误

如果你不想修改
power
的主体,你可以在它前面加上等式
power\n\124; assert(n>=0)False=undefined
(这个技巧是由于Oleg:)。是的,我意识到没有这个例子可能很难解释这一点,所以谢谢!
assertionCanary :: IO Bool
assertionCanary = do
    assertionsWorking <- try $ assert False $ return ()
    return $
      case assertionsWorking of
           Left (AssertionFailed _) -> True
           _                        -> False