下面的 smt2 代码给出了与类型相关的错误。
( declare-datatypes ( ( List 1 ) )
( ( par ( T ) ( ( cons ( hd T ) ( tl ( List T ) ) )
( nil )
) )
) )
(declare-sort Ty 0)
(define-fun-rec func ((x (List Ty) ) (y (List Ty))) (List Ty)
(match x ( ((cons xt xts) ( cons xt (func xts y)) )
( nil nil )
)
)
)
错误:
(error "Both branches of the ITE must be a subtype of a common type.
then branch: ((lambda ((xt Ty) (xts (List Ty))) (cons xt (func xts y))) (hd x) (tl x))
its type : (List Ty)
else branch: nil
its type : (List T)
")
为什么它不知道使用返回类型,有什么办法可以做到这一点吗?
一种方法是手动将其设置为 (nil (as nil (List Ty)) )
,这可以解决错误但我不想在每个 nil 处指定返回类型程序。
还有其他办法吗?或者我需要提及启用的任何选项?
最佳答案
这是设计使然。 SMTLib 的类型系统并非旨在进行任何类型的推理,而是为了使求解器能够轻松明确地加载规范。请参阅 http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf 的第 3.6 节其中讨论了良好排序的要求。因此,CVC4 理所当然地拒绝了您的程序。
但你是对的,这在实践中相当烦人。典型的解决方案是简单地在您感兴趣的类型上一劳永逸地定义所需的常量:
(define-fun nilTy () (List Ty) (as nil (List Ty)))
由于所有程序只能引用有限数量的排序,因此这始终是可能的。 (实际上,无论如何,像这样的不同种类很少存在;所以这不是一个大负担。这有时被称为“单态化”。)
一旦完成上述定义,您只需在适当的上下文中使用它而不是 nil
即可:
(define-fun-rec func ((x (List Ty) ) (y (List Ty))) (List Ty)
(match x ( ((cons xt xts) ( cons xt (func xts y)) )
( nil nilTy)
)
)
)
您会发现 CVC4 可以毫无困难地接受这一点,因为它现在确切地知道应该使用哪种 nilTy
。
请记住,SMTLib 通常不是手写的,而是机器生成的。因此,上述的笨拙通常并不适用,因为前端工具可以实现更高级的类型系统,并在幕后吐出所需的 SMTLib。希望有帮助!
关于smt - smt2 中的类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59207529/