水星是否支持代数谓词?

时间:2017-12-19 04:39:20

标签: mercury

我对Mercury和逻辑编程很新。我没有在文档或示例中找到这样的数字示例...

采用示例谓词:

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.

diffThirtyFour(A,B) :-
    ( B = A + 34.0 ).

这样,A必须被磨削,B是自由的。如果我希望A是自由的并且B要被接地(例如,添加mode diffThirtyFour(out,in) is det.),该怎么办?这种代数可以在编译时执行吗?我可以很容易地定义另一个谓词,但这似乎不合逻辑......

更新

所以,像这样的作品:

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is semidet.
:- mode diffThirtyFour(out, in) is semidet.

diffThirtyFour(A,B) :-
    ( B = A + 34.0, A = B - 34.0 ).

警惕semidet,以及第二个目标的冗余。这是唯一的方法吗?

更新2

这可能就是答案......它在编译时发出关于从不具有任何解决方案的析取的警告。一个正确的警告,但也许是不必要的代码味道?这就是我需要的,但是如果有更好的解决方案,请随意张贴......

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
:- mode diffThirtyFour(out, in) is det.



diffThirtyFour(A,B) :-
    ( A = B - 34.0, 
      B = A + 34.0 
    ; 
     error("The impossible happened...")
    ).

1 个答案:

答案 0 :(得分:2)

刚刚发现了输入different clauses for different modes的能力。这不是一个代数求解器(我无论如何也不会想到),但提供了我想要的精确组织结构:

:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
:- mode diffThirtyFour(out, in) is det.
:- pragma promise_pure(diffThirtyFour/2).

diffThirtyFour(A::out,B::in)  :- A = B - 34.0.
diffThirtyFour(A::in, B::out) :- B = A + 34.0.

如链接中所述,promise_pure编译指示是必需的,因为此功能可用于打破语义一致性。使用promise_equivalent_clauses pragma也足够了,它提供了逻辑一致性而没有纯度。仍然可以使用pred声明中的impure关键字声明具有不一致语义的子句。

有趣的是,标准int模块中的加法和减法是是不可逆的,但不在float模块中。也许是因为浮点运算中可能存在错误而做出选择....