Suppose I have the following grammar, representing types with one or more optional supertypes:
types([T]) --> type(T).
types([S|Ts]) --> super_type(S), types(Ts).
type(t1) --> [t1].
type(t2) --> [t2].
super_type(s1) --> [s1].
super_type(s2) --> [s2].
It generates the following output:
?- phrase(types(T), P).
T = P, P = [t1] ;
T = P, P = [t2] ;
T = P, P = [s1, t1] ;
T = P, P = [s1, t2] ;
T = P, P = [s1, s1, t1] ;
T = P, P = [s1, s1, t2] ;
T = P, P = [s1, s1, s1, t1] .
However, I would like each supertype
to appear at most once in an output list. How do I avoid generating an ever-expanding sequence of s1
's?
To clarify, I’d like a set of rules that would give me the following output:
?- phrase(types(T), P).
T = P, P = [t1] ;
T = P, P = [t2] ;
T = P, P = [s1, t1] ;
T = P, P = [s1, t2] ;
T = P, P = [s2, t1] ; % Added as per EricGT's comment
T = P, P = [s2, t2] ; % Added as per EricGT's comment
T = P, P = [s1, s2, t1] ;
T = P, P = [s1, s2, t2] ;
T = P, P = [s2, s1, t1] ;
T = P, P = [s2, s1, t2] ;
false
How can I do that with a DCG?
Note that I considered using memberchk/2 to test membership of a supertype in the output list, but that doesn’t work well because the output list is a difference list.
Edit: The ordering of results is not important, but the order of tokens makes a difference, so for example [s2,s1,t1]
is not the same as [s1,s2,t1]
. See comments below.