Как заставить мои отношения работать - PullRequest
1 голос
/ 06 июня 2011

У меня есть следующее отношение: индекс (X, N, список).

например:

index(X,2,[a,b,c]).
X=b

index(b,N,[a,b,c]).
N=2

Я не знаю, как заставить мое отношение работать со вторым примером. Это говорит о том, что N не определяется хорошо Вот мой код (он хорошо работает для первого примера).

index(X,1,[X|_]).
index(X,N,[_|Tail]) :- N > 1, N1 is N - 1 , index(X,N1,Tail).

Ответы [ 2 ]

0 голосов
/ 06 июня 2011

Существует встроенный SWI-Prolog nth1/3, который делает то, что вы хотите:

?- nth1(N, [a, b, c], b).
N = 2 ;
false.

Посмотрите на его исходный код:

?- listing(nth1).
lists:nth1(A, C, D) :-
    integer(A), !,
    B is A+ -1,
    nth0_det(B, C, D).
lists:nth1(A, B, C) :-
    var(A), !,
    nth_gen(B, C, 1, A).

true.

?- listing(nth0_det).
lists:nth0_det(0, [A|_], A) :- !.
lists:nth0_det(1, [_, A|_], A) :- !.
lists:nth0_det(2, [_, _, A|_], A) :- !.
lists:nth0_det(3, [_, _, _, A|_], A) :- !.
lists:nth0_det(4, [_, _, _, _, A|_], A) :- !.
lists:nth0_det(5, [_, _, _, _, _, A|_], A) :- !.
lists:nth0_det(A, [_, _, _, _, _, _|C], D) :-
    B is A+ -6,
    B>=0,
    nth0_det(B, C, D).

true.

?- listing(nth_gen).
lists:nth_gen([A|_], A, B, B).
lists:nth_gen([_|B], C, A, E) :-
    succ(A, D),
    nth_gen(B, C, D, E).

true.
0 голосов
/ 06 июня 2011

Переменная N не была создана для числового типа, когда Пролог пытается оценить цели N > 1 и N1 is N - 1 в рекурсивном предложении, определяющем index/3. Это вызывает ошибку инстанции, о которой вы сообщаете.

Я не знаю, как решить вашу проблему напрямую, но у меня есть два предложения. Первый - использовать аккумулятор, чтобы можно было оценить арифметические операции в рекурсивном предложении:

get(M,Xs,X) :- get(1,M,Xs,X).
get(N,N,[X|_],X).
get(N,M,[_|Xs],X) :-
  L is N + 1,
  get(L,M,Xs,X).

Например:

?- index(N,[a,b],X).
   N = 1,
   X = a ;
   N = 2,
   X = b ;
   false.

Другой - использовать тип натурального числа, чтобы индекс мог быть построен через объединение:

nat(0).
nat(s(N)) :- nat(N).

get(s(0),[X|_],X).
get(s(N),[_|Y],X) :- get(N,Y,X).

Например,

?- get(N,[a,b],X).
   N = s(0),
   X = a ;
   N = s(s(0)),
   X = b ;
   false.

Надеюсь, это было полезно. Возможно, кто-то более знающий придет и даст лучшее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...