<div dir="ltr">Hi,<div><br></div><div style>Nice to see that the mailing lists are still going, will Mercury still be OK after the move away from Melbourne?</div><div style><br></div><div style>As a learning exercise I have been trying to implement a solver for the "river crossing" problem in several logic languages. Below is my attempt in Mercury, however, it has a strange problem - namely, it only outputs an empty list. Can anyone tell me what's wrong?</div>
<div style><div><br></div><div>:- module river.</div><div>:- interface.</div><div>:- import_module io.</div><div>:- import_module list.</div><div>:- import_module solutions.</div><div><br></div><div>:- type object ---> chicken; fox; grain; nothing.</div>
<div>:- type side ---> left; right.</div><div>:- type riverstate ---> state(list(object), list(object), side).</div><div><br></div><div>:- pred eats(object::in,object::in) is semidet.</div><div>:- pred safe(list(object)::in) is semidet.</div>
<div>:- pred unsafe(list(object)::in) is semidet.</div><div>:- pred doMove(riverstate::in, object::in, riverstate::out) is nondet.</div><div>:- pred canMove(riverstate::in, object::out) is multi.</div><div>:- pred moveSafe(riverstate::in, object::out) is nondet.</div>
<div>:- pred solves(riverstate::in, riverstate::in, list(object)::out, list(riverstate)::in) is nondet.</div><div>:- pred main(io::di, io::uo) is det.</div><div><br></div><div>:- implementation.</div><div><br></div><div>eats(fox,chicken).</div>
<div>eats(chicken,grain).</div><div><br></div><div>safe(List) :- eats(A,B), member(A,List), member(B,List).</div><div><br></div><div>unsafe(List) :- not(safe(List)).</div><div><br></div><div>doMove(state(L,R,left),nothing,state(L,R,right)).</div>
<div>doMove(state(L,R,right),nothing,state(L,R,left)).</div><div>doMove(state(Left,Right,left), Item, state(NewLeft, NewRight, right)) :-</div><div> not (Item = nothing),</div><div> delete(Left,Item,NewLeft),</div><div>
sort([Item|Right],NewRight).</div><div>doMove(state(Left,Right,right), Item, state(NewLeft, NewRight, left)) :-</div><div> not (Item = nothing),</div><div> delete(Right,Item,NewRight),</div><div> sort([Item|Left],NewLeft).</div>
<div><br></div><div><br></div><div>canMove(_,nothing).</div><div>canMove(state(Left,_,left),Move) :- member(Move,Left).</div><div>canMove(state(_,Right,right),Move) :- member(Move,Right).</div><div><br></div><div>moveSafe(State,Move) :-</div>
<div> canMove(State,Move),</div><div> doMove(State,Move,state(Left,Right,Side)),</div><div> ( </div><div> (Side = left, safe(Right));</div><div> (Side = right, safe(Left))</div><div> ).</div><div><br></div><div>
solves(State,Target,[],_) :- State = Target.</div><div><br></div><div>solves(State,Target,[Move|SubPath],History) :-</div><div> not(State = Target),</div><div> moveSafe(State,Move),</div><div> doMove(State,Move,NewState),</div>
<div> not(member(NewState,History)),</div><div> solves(NewState,Target,SubPath,[State|History]).</div><div><br></div><div>main(!IO) :-</div><div> solutions( (pred(X::out) is nondet :- solves( state([chicken,fox,grain],[],left), state([],[chicken,fox,grain],right), X, [])),Result),</div>
<div> write(Result,!IO).</div><div><br></div><div style>Mark</div></div></div>