如何在函子OCaml中强制转换类型

时间:2013-07-22 15:09:33

标签: ocaml functor

我已经获得了关于OCaml中的仿函数的以下代码:

type comparison = Less | Equal | Greater;;

module type ORDERED_TYPE =
    sig
        type t
        val compare: t -> t -> comparison
    end
;;

module Set =
    functor (Elt: ORDERED_TYPE) ->
        struct
            type element = Elt.t
            type set = element list
            let empty = []
            let rec add x s =
                match s with
                | [] -> [x]
                | hd :: tl ->
                    match Elt.compare x hd with
                    | Equal -> s
                    | Less -> x :: s
                    | Greater -> hd :: add x tl
            let rec member x s =
                match s with
                | [] -> false
                | hd :: tl ->
                    match Elt.compare x hd with
                    | Equal -> true
                    | Less -> false
                    | Greater -> member x tl
    end
;;

module OrderedString : ORDERED_TYPE = 
    struct
        type t = string
        let compare x y =
            if x = y then Equal
            else if x < y then Less
            else Greater
    end
;;

module StringSet = Set(OrderedString);;

let out = StringSet.member "foo" (StringSet.add "foo" StringSet.empty);; (*compile error, where "foo" is expected OrderedString.t but actually is string*)

通过消除: ORDERED_TYPE

中的module OrderedString : ORDERED_TYPE =可以避免上述错误

只是无法理解为什么。

类似地,如果模块中有任何类型,如

module A = struct type t = string end;;

如何将字符串值指定为A.t类型,而不是实际string

感谢。

2 个答案:

答案 0 :(得分:4)

您可以在标准库中查看它是如何完成的:set.mli。 仿函数的签名是

module Make (Ord : OrderedType) : S with type elt = Ord.t

with type elt = Ord.t部分表示elt类型不是抽象的。

答案 1 :(得分:1)

正如Tomash所提到的,你缺少一个类型约束,但是没有在仿函数签名中(事实上你的代码中没有),但是在你给它的参数中。基本上,当你写

module OrderedString : ORDERED_TYPE = struct ... end

tOrderedString类型的定义将被抽象掉,因为tORDERED_TYPE签名中的抽象类型。你想要的是OrderedString确实是ORDERED_TYPE的实现,但是已知类型为t。这正是你将得到的

module OrderedString: ORDERED_TYPE with type t = string = struct ... end