Мне удалось ответить на мой собственный вопрос, но не с чистым решением.
Некоторые наблюдения
Трудность, возникающая при написании программы, планирующей выполнение некоторой цели, когда длина списка точно известна, заключается в том, что фактическое условие может измениться. Учти это:
when(fixed_length(L), Goal)
Длина списка может измениться, если L
не связан или если не связан последний конец. Скажем, у нас есть этот аргумент L = [_,_|Tail]
. L
имеет фиксированную ширину, только если Tail
имеет фиксированную ширину (другими словами, L
— это список, если T
— это список). Таким образом, условие, которое проверяет Tail
, может быть единственным, что нужно сделать вначале. Но если Tail
становится [a|Tail2]
, требуется новое условие, которое проверяет, является ли Tail2
списком.
Решение
<сильный>1. Получение условия-когда
Я реализовал предикат, который связывает неполный список с условием «когда», которое сигнализирует, когда он может стать списком (например, nonvar(T)
, где T
— это самый глубокий конец).
condition_fixed_length(List, Cond):-
\+ (List = []),
\+ \+ (List = [_|_]),
List = [_|Tail],
condition_fixed_length(Tail, Cond).
condition_fixed_length(List, Cond):-
\+ \+ (List = []),
\+ \+ (List = [_|_]),
Cond = nonvar(List).
<сильный>2. Рекурсивно при условии
check_on_fixed_length(List, Goal):-
(
condition_fixed_length(List, Condition)
->
when(Condition, check_on_fixed_length(List, Goal))
;
call(Goal)
).
Примеры запросов
Предположим, мы хотим проверить, что все элементы L
равны a
, когда размер L
фиксирован:
?- check_on_fixed_length(L, maplist(=(a), L)).
when(nonvar(L), check_on_fixed_length(L, maplist(=(a), L))).
... и затем L = [_,_|Tail]
:
?- check_on_fixed_length(L, maplist(=(a), L)), L = [_,_|L1].
L = [_G2887, _G2890|L1],
when(nonvar(L1), check_on_fixed_length([_G2887, _G2890|L1], maplist(=(a), [_G2887, _G2890|L1]))).
?- check_on_fixed_length(L, maplist(=(a), L)), L = [_,_|L1], length(L1, 3).
L = [a, a, a, a, a],
L1 = [a, a, a].
примесь
conditon_fixed_length/2
является источником нечистоты, как видно из следующего запроса:
?- L = [X, Y|Tail], condition_fixed_length(L, Cond), L = [a,a].
L = [a, a],
X = Y, Y = a,
Tail = [],
Cond = nonvar([]).
?- L = [X, Y|Tail], L = [a, a], condition_fixed_length(L, Cond).
false.
person
Tudor Berariu
schedule
19.01.2015
[]
,[_]
,[_,_]
. Но[_,_|_]
— это не список, это частичный список. Для этогоwhen(list(L), G)
может быть лучшим именем. - person false   schedule 19.01.2015[1|2]
. Но если только правильные списки являются реальными, это в некоторой степени означает, что правильные необходимы и для других терминов, таких как целые числа. - person false   schedule 19.01.2015Xs
также является неполным списком. Таким образом, любой терм является частичным списком, который сам не является списком, но имеет экземпляры, которые являются списками. - person false   schedule 19.01.2015