当试图在模块中为定义为int * int类型的变量赋值时:
let start : MazeProblem.state= (0,0)
我得到一个错误消息,类型不匹配。(问题出现在尝试搜索库从:https://www.lri.fr/filliatr/ftp/ocaml/ds/search.ml.html)
File "search_test1.ml", line 34, characters 33-38:
Error: This expression has type 'a * 'b
but an expression was expected of type MazeProblem.state
需要做什么才能使它工作?
#use "search.ml"
module Maze_FunctionalProblem = struct
type move = string
type state = int * int
let success s = let (x,y) = s in if (x==y && x==1) then true else false
let moves (s:state) : (move * state) list =
match s with
| (0,0) -> [ ("S", (1,0));("E",(0,1)) ]
| (0,1) -> [ ("S", (1,1));("W",(0,0)) ]
| (1,0) -> [ ("N", (0,0));("E",(1,1)) ]
| (1,1) -> [ ("N", (0,1));("W",(1,0)) ]
type table = (state, int) Hashtbl.t
let create (u:unit) = Hashtbl.create 100
let add (t:table) (s:state) : unit = Hashtbl.add t s 1
let mem (t:table) (s:state ): bool = Hashtbl.mem t s
let clear (t:table) = Hashtbl.clear t
end
module MazeProblem : FunctionalProblem = Maze_FunctionalProblem
module Test=FunctionalDFS(MazeProblem)
let start : MazeProblem.state= (0,0)
我希望OCaml的类型推断检测到(0,0)int*int类型与定义的结构兼容。
根据Glennsl在评论中的建议,并通过查看链接的FunctionalProblem
模块签名(如下所示)确认,MazeProblem.state
的类型为abstract
module type FunctionalProblem = sig type state type move val success : state -> bool val moves : state -> (move * state) list type table val create : unit -> table val add : table -> state -> unit val mem : table -> state -> bool val clear : table -> unit end
看下面一个更简单的例子,我们可以看到A
签名的应用使得C
摘要中的t
类型。在B
中不是抽象,所以我们可以直接将int
与B.f
一起使用,而在C.f
中这样做会导致编译错误。
# module type A = sig
type t
val f : t -> t
end
module B = struct
type t = int
let f x = x + 1
end
module C : A = B;;
module type A = sig type t val f : t -> t end
module B : sig type t = int val f : t -> t end
module C : A
# B.f 5;;
- : int = 6
# C.f 5;;
Error: This expression has type int but an expression was expected of type C.t
或者,我们可以公开t
的类型。
# module D : A with type t = int = B;;
module D : sig type t = int val f : t -> t end
# D.f 5;;
- : int = 6