Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/lib/reif.pl
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
/** Predicates from [*Indexing dif/2*](https://arxiv.org/abs/1607.01590).

The core trick that, unlike the traditional conditional `A -> B ; C`,
the branching condition is *not* provided as a complete goal.

Rather, the branching condition is a "reified goal",
i.e. a term which is completed with an additional argument `T`,
representing its satisfaction (`T = true`) and refutation (`T = false`).

Example:

```
Expand All @@ -19,6 +26,15 @@

:- meta_predicate(if_(1, 0, 0)).

%% if_(Cond_1, IfTrue, IfFalse).
% Monotonic if-then-else construct.
%
% Unlike `Cond_0 -> IfTrue; IfFalse`, this is nondeterministic in the condition.
% `Cond` is expected to be a reified goal.
% e.g. `if_((A=1), _, _)`
% where the `=` above is NOT the `(=)/2` predicate, but rather the `(=)/3` predicate
% defined in this module.

if_(If_1, Then_0, Else_0) :-
call(If_1, T),
( T == true -> call(Then_0)
Expand All @@ -27,13 +43,29 @@
; throw(error(instantiation_error, _))
).

%% =(X, Y, T).
% Reified equality predicate.
%
% `=(X,Y,true)` succeeds if X, Y *could* unify
% `=(X,Y,false)` succeeds if X, Y *could* fail to unify
% Partially call as a branching condition in `if_/3`:
% `if_(A=B, IfTrue, IfFalse)`

=(X, Y, T) :-
( X == Y -> T = true
; X \= Y -> T = false
; T = true, X = Y
; T = false, dif(X, Y)
).

%% dif(X, Y, T).
% Reified disequality predicate.
%
% `dif(X,Y,true)` succeeds if X, Y *could* fail to unify
% `dif(X,Y,false)` succeeds if X, Y *could* unify
% Partially call as a branching condition in `if_/3`:
% `if_(dif(A,B), IfTrue, IfFalse)`

dif(X, Y, T) :-
=(X, Y, NT),
non(NT, T).
Expand Down
Loading