After proagating the change to more code came across the example where the term could have different arity.
So this code (simplified for inclusion here) is wrong
error:hast_type(location,Location) :-
must_be(ground,Location),
Location = location(Location_name),
(
subsumes_term(location(_),Location)
;
throw(error(type_error(location, Location), _))
),
is_of_type(oneof([a,b,c]),Location_name).
error:hast_type(location,Location) :-
must_be(ground,Location),
Location = location(c,N),
(
subsumes_term(location(c,_),Location)
;
throw(error(type_error(location, Location), _))
),
must_be(nonneg,N).
because if location is location(c,1)
the first clause would see it as an error when in fact it should not cause an error.
This code works
error:hast_type(location,Location) :-
Location = location(Location_name), !,
must_be(ground,Location),
is_of_type(oneof([a,b,c]),Location_name).
error:hast_type(location,Location) :-
Location = location(c,N), !,
must_be(ground,Location),
must_be(nonneg,N).
error:hast_type(location,Location) :-
throw(error(domain_error(location, Location), _)).
This throws the error only when the other choices fail. Because this pattern fits better with domain_error
than type_error
used domain_error
.
Notice that the change follows the pattern
Head :-
Goal,
!,
Rest of clause.
as noted in “The Craft of Prolog” by Richard A. O`Keefe (WorldCat) is section 3.10 Pruning Alternative Solutions and was noted here.