2017-12-18 6 views
3

Ich habe gerade erst wurde in Prolog und ich hatte gehofft, dass die folgende Aufgabe auszuführen:Gibt es ein Äquivalent von Haskells enumFromTo in Prolog?

ein Prädikat A(P,N,L) so Sie sich, dass für alle C, die von L n-te Element ist, P(N,C).

Grundsätzlich möchte ich eine Karte auf den Bereich [0..N] durchführen. In Haskell, die Sprache, die ich am meisten vertraut bin mit, würde dies aussehen

f p n = map(p)[0..n] 

(Haskell nicht ganz haben Prädikate so einige Freiheiten hier nehme ich)

oder in pointfree

Und es scheint, ich sollte es in Prolog leicht genug tun können. Prologs maplist/3 ist im Grunde schon so, dass es eine triviale Modifikation sein sollte. Meine Definition sollte etwa so aussehen:

A(P,N,L) :- maplist(P, ??? , L). 

Allerdings kann ich nicht wirklich herausfinden, was in den Rohling zu setzen. In Haskell würde ich eine Funktion wie enumFromTo verwenden, aber es scheint, dass so etwas in Prolog nicht existiert. Das schließt äquivalent wäre between/3, aber das ist keine Liste, so dass ich nicht für maplist verwenden kann.

Alternativ könnte ich mein eigenes Bereichsprädikat machen.

Das erste, was ich versuchte, war:

range(0,[0]). 
range(N,[N|T]) :- range(N-1,T). 
A(P,N,L) :- range(N,rangeN), maplist(P, rangeN, L). 

Aber ich kann nicht, dass überhaupt zu lösen bekommen. Ich versuchte auch

range(N,L):-findall(X,between(0,N,X),L),sort(L,L). 
A(P,N,L) :- range(N,rangeN), maplist(P, rangeN, L). 

Aber das scheint nur wirklich klobig für so ein kleines Problem.

Wie könnte ich die Lücke in meinem maplist ausfüllen? Komme ich das Problem falsch an?

+1

Falscher Ansatz denke ich. Haskell ist faul, also ist die Zuordnung über eine Liste in Ordnung, da die ganze Liste niemals auf einmal existiert. In Prolog sollten Sie ein rekursives Prädikat machen, das nur eine Ganzzahl aktualisiert. –

Antwort

2
-- % f p n = map (p) [0..n] = [p 0, p 1, p 2, ..., p n] 

als

in Prolog übersetzt
f(P,N,L):- f(P,0,N,L). 
f(P,I,N,[]):- I > N. 
f(P,I,N,L):- call(P,I,X), 
      (N =:= I -> L = [X] 
      ; L = [X|T], J is I+1, f(P,J,N,T)). 

Dies setzt voraus, p :: Int -> a für einige a, wie durch den Code Haskell impliziert.

Dies setzt auch voraus, dass Sie ein konkretes ("Ground") zweistelliges Prädikat P und eine ganze Zahl N erhalten haben.

Eine andere Möglichkeit ist

g(P,N,L):- findall(X, (between(0, N, I), call(P,I,X)), L). 

Dies findet alle X s, so dass (0 <= I <= NundP(I,X)) hält.

in SWI-Prolog Geprüft:

11 ?- [user]. 
add1(X,Y):- Y is X+1. 
|: 

12 ?- f(add1,5,L). 
L = [1, 2, 3, 4, 5, 6]. 

13 ?- g(add1,5,L). 
L = [1, 2, 3, 4, 5, 6]. 
2

Als ich, wie gesagt von Picat Hause eine Lösung für N Damen-Problem zu Code in Prolog versuche (Beispiel 5, in der Nähe von Ende-Seite) Ich sah mich einem ähnlichen Problem gegenüber. Hier ist mein endgültiges Ergebnis, mit kommentierten einige Alternativen:

:- use_module(library(clpfd)). 

queens(N, Q) :- 
    length(Q, N), 
    Q ins 1..N, 
    all_different(Q), 
    maplist_index([I,V,P]>>(P#=V+I),1,Q,Ps),all_different(Ps), 
    maplist_index([I,V,M]>>(M#=V-I),1,Q,Ms),all_different(Ms), 
    /* no 
    bagof(P, (nth1(I,Q,V), P #= V + I), Ps), all_different(Ps), 
    bagof(M, (nth1(I,Q,V), M #= V - I), Ms), all_different(Ms), 
    */ 
    /* ok 
    all_different_p(Q, 1, P), all_different(P), 
    all_different_m(Q, 1, M), all_different(M), 
    */ 
    label(Q). 

all_different_p([Q|Qs], I, [P|Ps]) :- 
    P #= Q + I, 
    succ(I, J), 
    all_different_p(Qs, J, Ps). 
all_different_p([], _I, []). 

all_different_m([Q|Qs], I, [P|Ps]) :- 
    P #= Q - I, 
    succ(I, J), 
    all_different_m(Qs, J, Ps). 
all_different_m([], _I, []). 

maplist_index(P, I, [X|Xs], [Y|Ys]) :- 
    call(P, I, X, Y), 
    succ(I, J), 
    maplist_index(P, J, Xs, Ys). 
maplist_index(_, _, [], []). 

maplist_index/4 ist ein Beispiel dafür, was man braucht. Es ist erwähnenswert, dass bagof/3 in Gegenwart von attributierten Variablen nicht gut funktioniert.

Verwandte Themen