Haskell 契约“true”,这样“assert true x==x”就成立了
有没有可能写一份合同来检查一个陈述是否属实? 例如,我想定义一个合同Haskell 契约“true”,这样“assert true x==x”就成立了,haskell,contract,Haskell,Contract,有没有可能写一份合同来检查一个陈述是否属实? 例如,我想定义一个合同 true :: Contract a 对于所有的值x,方程 assert true x == x 坚持住 我试过这样的方法: true :: Contract a true = Pred (\a -> True) true :: Contract Bool true = Pred id 但当运行assert true x==x时,编译器会说x是未定义的。 当运行asserttrue 5==6时,结果为False
true :: Contract a
对于所有的值x,方程
assert true x == x
坚持住
我试过这样的方法:
true :: Contract a
true = Pred (\a -> True)
true :: Contract Bool
true = Pred id
但当运行assert true x==x时,编译器会说x是未定义的。
当运行asserttrue 5==6时,结果为False,我希望出现违反合同的错误。
我应该如何更改这个真实的合同?谢谢你的帮助
这里
如果违反约定,Assert将导致运行时失败,否则将返回原始结果:
assert :: Contract a -> a -> a
assert (Pred p) x = if p x then x else error "contract violation"
assert (Fun pre post) f = assert post . f . assert pre
如果你认为你的定义是正确的和肯定的,你就能很清楚地看到问题。以下是相关部分:
true :: Contract a
true = Pred (\a -> True)
assert :: Contract a -> a -> a
assert (Pred p) x = if p x then x else error "contract violation"
...
将它们放在一起,您会看到assert true x将测试\a->true x,并根据是真是假生成x或抛出错误。不管你对x使用什么表达式,这都是真的,因为根据定义谓词总是返回真的,并且忽略它的参数
简单的解决方法是让真正的契约实际测试其论点,如下所示:
true :: Contract a
true = Pred (\a -> True)
true :: Contract Bool
true = Pred id
也就是说,这个新的true只能应用于Bool类型的值,因为它对其他任何值都没有意义,并且对它没有任何作用。如果该值为True,则允许该值通过,否则将抛出所需的违反合同错误:
Prelude> assert true (5==6)
*** Exception: contract violation
CallStack (from HasCallStack):
error, called at <interactive>:21:46 in interactive:Ghci2
Prelude> assert true (5==5)
True
请注意assert true 5==6中的括号,因为assert true 5==6被解析为assert true 5==6,因为函数应用程序是Haskell中最优先的运算符。断言true 5==6会导致错误,因为此更正版本的true仅适用于布尔值,因此不适用于5。请注意,断言true x==x会将断言true x与x进行比较;所以断言true 5是5,当然5==6是false,不是违反合同
如果您打算将断言true x==x改为保持,那么
true :: Contract Bool
true = Pred id
assert true (5==6) -- Contract violation
是您在运行assert true x==x时想要的编译器说x未定义在这里相当关键。在我看来,您的断言调用是一个表达式,其中包含对x的两个引用,最外层的函数是==。没有x的绑定,任何一方都无法计算。assert true x部分永远不会看到==,如果我们重写它来assert true x==x,我们仍然需要提供一个x::Eq a。我不知道如何检查函数本身,但肯定有一些选项我不太熟悉 我想这是在使用图书馆。您能指定您正在使用的库吗?@bradrn我不知道。我自己定义了契约类型和断言函数,那么您能为我们提供定义吗?除非我们知道你在用什么,否则我们帮不了你。@bradrn我知道了。在这个词后面,在问题的末尾。我编辑了问题侧注释:Haskell有很多表达式,而不是报告中描述的do as语句中的导入和条目。