caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Goswin von Brederlow <goswin-v-b@web.de>
To: <caml-list@inria.fr>
Subject: [Caml-list] Odd failure to infer types
Date: Sat, 03 Sep 2011 11:53:30 +0200	[thread overview]
Message-ID: <87ty8uc5ph.fsf@frosties.localnet> (raw)

Hi,

I'm implementing a solver for the game Atomix. If you don't know it then
don't worry. It isn't relevant.

I split things up into submodules and now one of the submodules does not
infere the right types:

File "Atomix.ml", line 168, characters 11-876:
Error: The type of this module,
       sig
         type dir = NORTH | SOUTH | WEST | EAST
         val max_moves : int
         val cache : (string, unit) Hashtbl.t
         val states :
           ('_a list * (char * int * int) array * string) list array
         val string_of_dir : dir -> string
         val print :
           (int * int * dir) list * (char * int * int) array * string -> unit
         val num_states : int
       end, contains type variables that cannot be generalized

I believe this is wrong. In S.num_states the call to "print state"
fixates the type for state and the "states.(d) <- state::states.(d);"
should then fixate the missing '_a in the type for states.

Anyone know why?

MfG
        Goswin

----------------------------------------------------------------------
module B = struct
  exception Outside
  let width = 14
  let height = 6
  let board = ""
    ^ "  #         # "
    ^ "  #         # "
    ^ "  #           "
    ^ "  # #  #######"
    ^ "    #         "
    ^ "    #         "

  let start =
    Array.of_list
      (List.sort compare
	 [
	   ('A',  1, 3); (*  H- *)
	   ('B', 10, 5); (* -O- *)
	   ('C', 13, 1); (* -H  *)
	 ])

  let get board x y =
    if (x < 0) || (x >= width) || (y < 0) || (y >= height)
    then '#'
    else board.[x + y * width]

  let set board x y c =
    if (x < 0) || (x >= width) || (y < 0) || (y >= height)
    then raise Outside;
    let board = String.copy board
    in
    board.[x + y * width] <- c;
    board

  let print board =
    Printf.printf "  ";
    for x = 0 to width - 1 do
      Printf.printf "%c" (char_of_int (int_of_char 'A' + x));
    done;
    Printf.printf "\n";
    Printf.printf " +--------------+\n";
    for y = 0 to height - 1 do
      Printf.printf "%d|" (y + 1);
      for x = 0 to width - 1 do
	Printf.printf "%c" board.[y * width + x];
      done;
      Printf.printf "|\n";
    done;
    Printf.printf " +--------------+\n";
    flush_all ()
end

module G = struct
  let width = 3
  let height = 1
  let atoms = "ABC"

  let get x y =
    if (x < 0) || (x >= width) || (y < 0) || (y >= height)
    then '~'
    else atoms.[x + y * width]
    
  let solutions =
    let rec loopy acc = function
      | -1 -> acc
      | y ->
	let rec loopx acc = function
	  | -1 -> loopy acc (y - 1)
	  | x ->
	    let rec loopv acc sol board = function
	      | -1 ->
		B.print board;
		let sol = Array.of_list (List.sort compare sol)
		in
		loopx ((sol, board)::acc) (x - 1)
	      | v ->
		let rec loopu acc sol board = function
		  | -1 -> loopv acc sol board (v - 1)
		  | u ->
		    let c = get u v
		    in
		    if c = ' '
		    then loopu acc sol board (u - 1)
		    else if B.get board (x + u) (y + v) = ' '
		    then
		      begin
			let board = B.set board (x + u) (y + v) c
			in
			loopu acc ((c, x + u, y + v)::sol) board (u - 1)
		      end
		    else loopx acc (x - 1) 
		in
		loopu acc sol board (width - 1)
	    in
	    loopv acc [] B.board (height - 1)
	in
	loopx acc (B.width - width)
    in
    loopy [] (B.height - height)

  let print (sol, board) =
    B.print board;
    Array.iter
      (fun (c, x, y) ->
	Printf.printf "%c: (%c, %d)\n" c
	  (char_of_int (int_of_char 'A' + x))
	  (y + 1))
      sol;
    flush_all ()
end

module D = struct
  let infty = 999999
  let make_one x y =
    let d = Array.make_matrix B.width B.height infty in
    let rec loop n acc = function
      | [] ->
	if acc = []
	then d
	else loop (n + 1) [] acc
      | (u, v)::xs ->
	let rec move acc x y dx dy =
	  if B.get B.board x y = ' '
	  then
	    let acc =
	      if d.(x).(y) > n
	      then
		begin
		  d.(x).(y) <- n;
		  (x, y)::acc
		end
	      else acc
	    in
	    move acc (x + dx) (y + dy) dx dy
	  else acc
	in
	let acc = move acc u v (-1) 0 in
	let acc = move acc u v 1 0 in
	let acc = move acc u v 0 (-1) in
	let acc = move acc u v 0 1
	in
	loop n acc xs
    in
    d.(x).(y) <- 0;
    loop 1 [] [(x, y)]

  let dist =
    Array.init B.width (fun x -> Array.init B.height (fun y -> make_one x y))

  let get x1 y1 x2 y2 =
    if (x1 < 0) || (x1 >= B.width) || (y2 < 0) || (y2 >= B.height)
      || (x2 < 0) || (x2 >= B.width) || (y2 < 0) || (y2 >= B.height)
    then infty
    else dist.(x1).(y1).(x2).(y2)

  let get_all pos =
    let d =
      Array.mapi
	(fun i (c, x1, y1) ->
	  let (_, x2, y2) = B.start.(i)
	  in
	  get x1 y1 x2 y2)
	pos
    in
    Array.fold_left ( + ) 0 d
end

module S = struct
  type dir = NORTH | SOUTH | WEST | EAST

  let max_moves = 1000
  let cache = Hashtbl.create 0
    (*
  let states = ((Array.make max_moves []) :
      ((int * int * dir) list * (char * int * int) array * string) list array)
    *)
  let states = Array.make max_moves []

  let string_of_dir = function
    | NORTH -> "norden"
    | SOUTH -> "sueden"
    | WEST -> "westen"
    | EAST -> "osten"
      
  let print (moves, (_ : (char * int * int) array), board) =
    B.print board;
    List.iter
      (fun (x, y, dir) ->
	Printf.printf "zug %c %d %s,"
	  (char_of_int (int_of_char 'A' + x))
	  (y + 1)
	  (string_of_dir dir))
      moves

  let num_states =
    List.fold_left
      (fun num (sol, board) ->
	let d = D.get_all sol in
	let state = ([], sol, board)
	in
	Hashtbl.add cache board ();
	states.(d) <- state::states.(d);
	print state;
	num + 1)
      0
      G.solutions
end

let () =
  List.iter G.print G.solutions;
  Printf.printf "%d solutions\n" (List.length G.solutions)

             reply	other threads:[~2011-09-03  9:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-03  9:53 Goswin von Brederlow [this message]
2011-09-03 10:31 ` Christophe Papazian
2011-09-03 11:42   ` Guillaume Yziquel
2011-09-03 10:36 ` Guillaume Yziquel
2011-09-03 11:35   ` Philippe Veber
2011-09-03 11:46     ` Guillaume Yziquel
2011-09-03 12:15       ` Gabriel Scherer
2011-09-03 12:50         ` Guillaume Yziquel
2011-09-17 12:08         ` Goswin von Brederlow
2011-09-18  7:26           ` Gabriel Scherer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ty8uc5ph.fsf@frosties.localnet \
    --to=goswin-v-b@web.de \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).