我有不同逻辑运算符的真值表;
truthtable a1
| a1 == "mynot" = [(p,q,r,s) | p <- [0,1], q <- [0,1], let r = mynot p, s <- ["mynot"]]
| a1 == "myand" = [(p,q,r,s) | p <- [0,1], q <- [0,1], let r = myand p q, s <- ["myand"]]
| a1 == "myor" = [(p,q,r,s) | p <- [0,1], q <- [0,1], let r = myor p q, s <- ["myor"]]
| a1 == "myimply" = [(p,q,r,s) | p <- [0,1], q <- [0,1], let r = myimply p q, s <- ["myimply"]]现在,我必须创建一个函数(equiv)来确定两个操作符的行为是否相同,如果不是,则给出一个反例。因此,对于equiv "myimply" "myimply",它应该确定它是等价的,但是对于equiv "myimply" "myor",它应该调用函数counterEx,这给出了一个反例(运算符不同)。
现在我有了这个:
equiv a1 a2
| truthtable a1 == truthtable a2 = True
| otherwise = counterEx a1 a2
counterEx a1 a2 = truthtable a1 ++ truthtable a2但当然,equiv有不同的结果,因此是不可能的。然而,我真的不知道如何才能给出一个更好的反例(而不是仅仅给出所有的可能性,你就会看到哪些是不同的)。同样,如果真值表不等价,我也不知道如何调用函数counterEx,而只是在真值表确实相同的情况下才确定它们相同。
发布于 2019-09-28 14:55:01
这里最常用的解决方案是使用自定义的返回数据类型
type TTable = [(Int,Int,Int,Int)]
data EquivResult
= Equivalent
| NotEquivalent TTable
equiv :: TTable -> TTable -> EquivResult
equiv a1 a2
| truthtable a1 == truthtable a2 = Equivalent
| otherwise = NotEquivalent (counterEx a1 a2)也可以使用Maybe TTable来代替定义自定义的EquivResult,但是不太明显的是,Nothing的意思是“等价的”,而Just _的意思是"_是一个反例“。
equiv :: TTable -> TTable -> Maybe TTable
equiv a1 a2
| truthtable a1 == truthtable a2 = Nothing
| otherwise = Just (counterEx a1 a2)顺便问一下,为什么要将整数0和1用于布尔值?为什么不是Bool类型的False和True呢?对布尔值使用Int感觉很奇怪,并且允许使用像2这样的无效值。
(作为一般建议,我建议通过声明其类型来开始编写每个函数。类型签名对于迅速检测潜在错误以及帮助编译器生成更好的错误消息非常重要。)
https://stackoverflow.com/questions/58143848
复制相似问题