I’m not suggesting Prolog needs a type system.
But in some cases where I have unruly states to track, I’d like some of the peace of mind one gets with type inference, completeness checks, etc.
It occurred to me that the domain
example at Attributed variables gives a foundation of a “poor man’s type checker”.
After some minor changes:
domain(X, Dom) :-
var(Dom), !,
get_attr(X, domain, Dom).
domain(X, List) :-
list_to_set(List, Domain),
put_attr(Y, domain, Domain),
X = Y.
% a sort of unified intersection
unisection(List1, List2, Set) :-
findall(X, (member(X,List1), member(X,List2)), List3),
list_to_set(List3, Set).
attr_unify_hook(Domain, Y) :-
( get_attr(Y, domain, Dom2)
-> unisection(Domain, Dom2, NewDomain),
( NewDomain == []
-> fail
; NewDomain = [Value]
-> Y = Value
; put_attr(Y, domain, NewDomain)
)
; var(Y)
-> put_attr( Y, domain, Domain )
; member(Y, Domain)
).
Then we can have a domain-match-checker.
is_maybe(Y) :- domain(Y, [nothing, just(_)]).
maybe_map(F,MaybeY,D) :-
is_maybe(MaybeY),
(
MaybeY = nothing,
D = nothing
;
MaybeY = just(Y),
call(F,Y,X),
D = just(X)
) .
maybe_map(F,MaybeY,D) :-
\+ is_maybe(MaybeY), type_error(maybe,MaybeY).
Then use it all:
inc(X,Y) :- #(Y) #= #(X) + 1.
?- domain(X, [M, pizza]), maybe_map(inc, X ,Y).
X = Y, Y = nothing ;
X = just(_A),
Y = just(_B),
clpfd: #=(_A+1, _B) ;
Now I haven’t actually used this yet in my real code. But at first glance it looks like what I think I want for my peace of mind.
Any objections or suggestions?