Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 契约“true”,这样“assert true x==x”就成立了_Haskell_Contract - Fatal编程技术网

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语句中的导入和条目。