我正在尝试使用这个Haskell包:
https://hackage.haskell.org/package/z3
是Z3 C API的包装器,用于处理相互递归的数据类型。作为测试,我试图将以下SMT2脚本转换为Haskell函数。
(declare-datatypes () ((X (a (y Y)) ac)
(Y (b (x X)) bc)))
(declare-const a_v (X))
(declare-const b_v (Y))
(assert (= a_v (a b_v)))
(check-sat)
(get-model)
目前,我能找到最接近的方法是:
mutuallyRecursive :: IO (Result, Maybe Model)
mutuallyRecursive = evalZ3 mutuallyRecursive'
where
mutuallyRecursive' :: Z3 (Result, Maybe Model)
mutuallyRecursive' = do
x' <- mkStringSymbol "X"
y' <- mkStringSymbol "Y"
_x <- mkStringSymbol "x"
_y <- mkStringSymbol "y"
a' <- mkStringSymbol "a"
ac' <- mkStringSymbol "ac"
b' <- mkStringSymbol "b"
bc' <- mkStringSymbol "bc"
is_a <- mkStringSymbol "is-a"
is_ac <- mkStringSymbol "is-ac"
is_b <- mkStringSymbol "is-b"
is_bc <- mkStringSymbol "is-bc"
b <- mkConstructor b' is_b [] --Should contain an X
bc <- mkConstructor bc' is_bc []
y <- mkDatatype y' [b, bc]
a <- mkConstructor a' is_a [(_x, Just y, 0)]
ac <- mkConstructor ac' is_ac []
x <- mkDatatype x' [a, ac]
a_v' <- mkStringSymbol "a_v"
b_v' <- mkStringSymbol "b_v"
a_v <- mkConst a_v' x
b_v <- mkConst b_v' y
[a_func, _] <- getDatatypeSortConstructors x
a_b_v <- mkApp a_func [b_v]
assert =<< mkEq a_v a_b_v
solverCheckAndGetModel
请注意,数据类型为Y的构造函数b在我的Haskell实现中是不正确的。它缺少类型X的参数。但是,我不能直接包含排序X,因为它尚未声明。但是如果我交换了X和Y定义的顺序,我明显遇到了同样的问题,只是逆转了(即,我需要,但不能在X中引用Y.)
基于此页面上的MkConstructor定义(涉及C api,而不是Haskell api):
我想也许我必须将[(symbol,Nothing,#)]形式的东西传递给mkConstructor,其中#是数据类型X的一些非零标识符。但我不是百分之百确定这是正确的,并且即使是,我也不知道如何获得#。任何帮助解决这个问题将不胜感激。