Mercury 是否支持代数谓词?
Are algebraic predicates supported in 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
这可能就是答案...它会在编译时发出警告,说明析取永远没有任何解。一个正确的警告,但也许是不必要的代码味道?这就是我需要的,但如果有更好的解决方案,请随时 post 他们...
:- 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...")
).
刚刚发现进入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.
如 link 中所述,promise_pure
杂注是必需的,因为此功能可用于破坏语义一致性。使用 promise_equivalent_clauses
pragma 也足够了,它保证了逻辑上的一致性而不是纯粹的。仍然可以在 pred 声明中使用 impure
关键字声明语义不一致的子句。
有趣的是,标准int
模块中的加法和减法是可逆的,但在float
模块中则不然。也许是因为浮点运算中可能存在错误而做出的选择....
我对 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
这可能就是答案...它会在编译时发出警告,说明析取永远没有任何解。一个正确的警告,但也许是不必要的代码味道?这就是我需要的,但如果有更好的解决方案,请随时 post 他们...
:- 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...")
).
刚刚发现进入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.
如 link 中所述,promise_pure
杂注是必需的,因为此功能可用于破坏语义一致性。使用 promise_equivalent_clauses
pragma 也足够了,它保证了逻辑上的一致性而不是纯粹的。仍然可以在 pred 声明中使用 impure
关键字声明语义不一致的子句。
有趣的是,标准int
模块中的加法和减法是可逆的,但在float
模块中则不然。也许是因为浮点运算中可能存在错误而做出的选择....