<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>