代码之家  ›  专栏  ›  技术社区  ›  Kon

OCaml中的模块类型语义

  •  1
  • Kon  · 技术社区  · 5 月前

    我是OCaml的新手,在理解模块类型的工作原理方面有点困难。

    module type I = sig
      type t
    end
    
    module EQ (M : I) = struct
      let equal (x : M.t) (y : M.t) = x = y
    end
    
    (* Explicitly type declaration *)
    module A : I = struct
      type t = string
    end
    
    module EStr1 = EQ (A)
    
    (* Error: This expression has type string but an expression was expected of type
             A.t *)
    let _ = EStr1.equal "1" "0" |> string_of_bool |> print_endline
    
    (* No type declaration *)
    module B = struct
      type t = string
    end
    
    module EStr2 = EQ (B)
    
    (* OK. Outputs false *)
    let _ = EStr2.equal "1" "0" |> string_of_bool |> print_endline
    
    

    在上面的代码中,我声明了模块类型 I ,模块 A 具有显式的模块类型声明和模块 B 没有模块类型声明。 EQ 是接收类型为的模块的函数子 一、 并返回模块 equal 方法。

    模块示例 A. 导致编译错误,而另一个则按我的预期工作。这些例子之间的语义差异是什么?

    1 回复  |  直到 5 月前
        1
  •  1
  •   Chris    5 月前

    顶层解释器的输出具有指导意义。

    # module type I = sig
      type t
    end
    
    module EQ (M : I) = struct
      let equal (x : M.t) (y : M.t) = x = y
    end
    
    (* Explicitly type declaration *)
    module A : I = struct
      type t = string
    end
    
    module EStr1 = EQ (A);;
    module type I = sig type t end
    module EQ : functor (M : I) -> sig val equal : M.t -> M.t -> bool end
    module A : I
    module EStr1 : sig val equal : A.t -> A.t -> bool end
    

    注意签名 EStr1 模块。 EStr1.equal 具有类型 A.t -> A.t -> bool .不是类型 string -> string -> bool .

    应用 I 签名到 A 限制了我们了解 什么 A.t 是。它是一种抽象类型。你还没这么做 B ,所以 EStr2.equal 确实有类型 string->string->bool .

    您还可以显式公开此类型信息。

    # module A : I with type t = string = struct
      type t = string
    end;;
    module A : sig type t = string end
    # module C = EQ (A);;
    module C : sig val equal : string -> string -> bool end
    

    一旦你理解了抽象类型的工作原理,它们就非常有用。