Debugging OCaml模块错误

Debugging OCaml模块错误,debugging,ocaml,Debugging,Ocaml,当我试图将函子板传递给数独时,它有以下错误 我应该在.ml文件中做什么来匹配接口?如何初始化模块板并将其传递到数独模块 error: The implementation modularSudoku.ml does not match the interface modularSudoku.cmi: Modules do not match: functor (B : Board1) -> sig

当我试图将函子板传递给数独时,它有以下错误 我应该在.ml文件中做什么来匹配接口?如何初始化模块板并将其传递到数独模块

error: The implementation modularSudoku.ml
       does not match the interface modularSudoku.cmi:
       Modules do not match:
         functor (B : Board1) ->
           sig
             val pick : B.grid -> (B.grid * B.location * B.grid) option
             val update_at_loc :
               B.grid -> B.location -> square -> B.grid option
             val update_grid : B.grid -> B.location -> B.grid option
             val is_solved : B.grid -> bool
             val solve_sudoku : B.grid -> B.grid list -> B.grid list
             val backtrack : B.grid list -> B.grid list
           end
       is not included in
         functor
           (Board : sig
                      type location
                      type grid
                      val first_location : location
                      val next : location -> location option
                      val same_row_col_block : location -> location -> bool
                      val get_square : grid -> location -> square
                      val change_square : grid -> location -> square -> grid
                    end) ->
           sig
             val pick :
               Board.grid ->
               (Board.grid * Board.location * Board.grid) option
             val update_grid :
               Board.grid -> Board.location -> Board.grid option
             val is_solved : Board.grid -> bool
             val solve_sudoku :
               Board.grid -> Board.grid list -> Board.grid list
           end
       Modules do not match:
         sig
           type location
           type grid
           val first_location : location
           val next : location -> location option
           val same_row_col_block : location -> location -> bool
           val get_square : grid -> location -> square
           val change_square : grid -> location -> square -> grid
         end
       is not included in
         Board1
       Type declarations do not match:
         type location
       is not included in
         type location = int * int
这是Sudoku.mli文件

type square = Picked of int | Possible of int list;;

module Sudoku :
  functor (Board: sig
    type location;;
    type grid;;

    val first_location: location;;
    val next : location -> location option;;
    val same_row_col_block : location -> location -> bool;;
    val get_square : grid -> location -> square;;
    val change_square : grid -> location -> square -> grid;;
  end) -> (sig
    open Board;;
    val pick : grid -> (grid * location * grid) option;;
    val update_grid : grid -> location -> grid option;;
    val is_solved : grid -> bool;;
    val solve_sudoku : grid -> grid list -> grid list;;
  end)
;;

module Board1 : sig
  type location = (int*int);;
  type grid = square list;;
  val first_location: location;;
  val next : location -> location option;;
  val same_row_col_block : location -> location -> bool;;
  val get_square : grid -> location -> square;;
  val change_square : grid -> location -> square -> grid;;
end
这里是Sudoku.ml文件 类型square=整数的选取|整数列表的可能

let create_grid l = List.map (fun x ->  match x with 0 -> Possible [1;2;3;4;5;6;7;8;9] | _ -> Picked x) l;;

(*test*)
let easyGrid = create_grid
       [ 0 ; 6 ; 0 ; 0 ; 4 ; 0 ; 0 ; 0 ; 0
       ; 3 ; 0 ; 7 ; 1 ; 0 ; 9 ; 0 ; 0 ; 6 
       ; 0 ; 9 ; 4 ; 2 ; 0 ; 5 ; 7 ; 0 ; 0
       ; 0 ; 3 ; 1 ; 0 ; 0 ; 0 ; 4 ; 0 ; 0 
       ; 2 ; 0 ; 0 ; 4 ; 0 ; 7 ; 0 ; 0 ; 5
       ; 0 ; 0 ; 6 ; 0 ; 0 ; 0 ; 9 ; 7 ; 0 
       ; 0 ; 0 ; 2 ; 3 ; 0 ; 8 ; 6 ; 1 ; 0
       ; 6 ; 0 ; 0 ; 9 ; 0 ; 2 ; 8 ; 0 ; 4 
       ; 0 ; 0 ; 0 ; 0 ; 1 ; 0 ; 0 ; 9 ; 0];;


module type Board1 = sig
  type location = (int*int);;
  type grid = square list;;
  val first_location: location;;
  val next : location -> location option;;
  val same_row_col_block : location -> location -> bool;;
  val get_square : grid -> location -> square;;
  val change_square : grid -> location -> square -> grid;;
end

module Board1 = 
  struct 
    type location = (int*int)
    type grid = square list
    let first_location = (0,0)
    let next (i,j) = 
        if j+1 = 9 then
      if i+1 = 9 then None
      else Some (i+1,0)
    else Some (i,j+1)
    let same_row_col_block (i1,j1) (i2,j2) =
      (i1 = i2) || (j1 = j2) || ((i1/3 = i2/3) && (j1/3 = j2/3))
    let get_square grid (i, j) = List.nth grid (9*i + j)
    let change_square grid (i, j) square =
      let k = i * 9 + j in 
      let rec helper t acc n =
    if n = k then List.rev_append acc (square :: (List.tl t))
    else helper (List.tl t) (List.hd t :: acc) (n+1) in
      helper grid [] 0

end;;


module Sudoku =
  functor (B:Board1)-> 
    struct
      let pick grid =
    let rec helper loc =
      match B.get_square grid loc with
       | Picked _ -> (match B.next loc with
             | None -> None
         | Some loc1 ->  helper loc1)
       | Possible l ->
           (match l with
           | [] -> None
           | x :: xs -> let new_grid = B.change_square grid loc (Picked x) in
                 let choice_grid = B.change_square grid loc (Possible xs) in
                 Some (new_grid, loc, choice_grid)) in
    helper B.first_location
      let update_at_loc grid loc square =
    let square1 = B.get_square grid loc in
    match square,square1 with
    | Picked x, Picked y -> if x = y then None else Some grid
    | Picked x, Possible l ->
        if List.mem x l
        then let l' = List.filter (fun y -> not (y = x)) l in
            if List.length l' == 0 then None else Some (B.change_square grid loc (Possible l'))
        else Some grid
    | _ -> assert false 
      let update_grid grid loc =
    let square = B.get_square grid loc in 
    let apply_constraint loc1 grid =update_at_loc grid loc1 square in
    let rec help loc1 grid = 
      let g =
        if loc = loc1
        then Some grid
        else if B.same_row_col_block loc loc1
        then apply_constraint loc1 grid
        else Some grid in

      match g with
      | None -> None
      | Some newgrid ->
          (match B.next loc1 with
          | None -> g
          | Some loc2 -> help loc2 newgrid) in 

    help B.first_location grid
      let is_solved grid =
    let rec helper loc =
       match B.get_square grid loc with
       | Possible _ -> false
       | Picked _ -> match B.next loc with
             | None -> true
         | Some loc1 -> helper loc1 in
    helper B.first_location

      let rec solve_sudoku grid choices =
    match pick grid with
    | None -> if is_solved grid then (*let () = print_sudoku grid in*) grid :: backtrack choices
    else backtrack choices
    | Some (g,loc,ch) ->
        (match update_grid g loc with
        | None -> backtrack (ch::choices)
        | Some grid -> (*let () = print_sudoku grid in*)
                solve_sudoku grid (ch::choices))

      and backtrack choices =
    match choices with
    | [] -> []
    | g :: grids -> solve_sudoku g grids
end
;;

在.mli中,函子
Sudoku
被指定为使用类型为
location
grid
的参数模块,但对这些类型没有限制。例如,根据.mli中的规范,我应该能够应用

module A = struct type location = bool type grid = unit (* ... *) end
module S = Sudoku(A)
但是,在.ml中定义函子时,要求参数的这些类型分别等于
int*int
square list
。显然,这更具限制性(尤其是与参数签名相匹配的模块更少,而不是上面的
A
),因此函子本身与.mli中更宽松的规范不匹配(这也称为逆变)

有没有理由不在.mli中用相同的签名
Board1
注释函子参数
B
?那么它显然会起作用