Detect type when target is a list with an unground tail?

I’m using: SWI-Prolog version 8.1.9.

How can I tell if something is a list when it has a tail that is not ground? is_list and is_of_type both return false if the list has an unground tail, which means I can’t use them with difference lists.

[debug] 16 ?- is_of_type(list, [a|T]).
false.

[debug] 19 ?- is_list([a|T])
false

Try this definition for is_list:

is_list(X) :-
    freeze(X, is_list2(X)).

is_list2([]).
is_list2([_|Xs]) :-
    is_list(Xs).

e.g.:

?- X = [1,2,|Y], is_list(X), Y = [].

I’ll leave it as an “exercise for the reader” as to why your original is_list failed. (Hint: should it have succeeded? If so, what about X = [1,2|Y], is_list(X), Y = 3?)

A list is defined as ending in []. If it ends in something else it is not a list. It may be a partial list or, more in general, terms may be of some partial type. This means the term is a generalization of an instance of that type. The current library(error) has no support for partial types.

So, your only way out is to walk the list, finding the first non [_|_] cell and test it for being a variable.

Somewhere in my archives I have code that does something related to @peter.ludemann’s suggestion: if a term is a partial something, add constraints to the variables that force the term to remain compatible with the indicated type. I think there is some potential in this notion, but I never found the time to deeply look into it.

2 Likes