当前位置: 动力学知识库 > 问答 > 编程问答 >

debugging - OCaml Module error

问题描述:

When I trying to pass functor Board to Sudoku it has following error

What should i do in the .ml file to match the interface? How do i initialize the module Board and pass it into the Sudoku Module?

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

Here is Sudoku.mli file

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

Here is Sudoku.ml file

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

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

;;

网友答案:

In your .mli, the functor Sudoku is specified to expect an argument module with types location and grid, but with no restriction on what these types are. For example, according to the spec in the .mli, I should be able to apply

module A = struct type location = bool type grid = unit (* ... *) end
module S = Sudoku(A)

However, in the .ml you define the functor such that it requires the argument to have these types equal to int * int and square list, respectively. Clearly, that is more restrictive (fewer modules match that argument signature, in particular, not the above A), and hence the functor itself does not match the more liberal specification in the .mli (this is also known as contravariance).

Is there a reason why you don't just annotate the functor parameter B with the same signature Board1 in the .mli as well? Then it would clearly work.

分享给朋友:
您可能感兴趣的文章:
随机阅读: