Debugging OCaml模块错误
当我试图将函子板传递给数独时,它有以下错误 我应该在.ml文件中做什么来匹配接口?如何初始化模块板并将其传递到数独模块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
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
?那么它显然会起作用