【问题标题】:How to make a value of type which is defined with module in OCaml?如何在 OCaml 中使用模块定义的类型值?
【发布时间】:2020-04-25 16:32:40
【问题描述】:

TL;DR - 在 OCaml 中,如何调用类似于 type 'elt set = (module BatSet.S with type elt = 'elt) 的类型以及如何生成该类型的值?

目前,我正在阅读 Tezos 协议[*] 中的代码,我看到了以下代码。

module type Boxed_set = sig
  type elt
  val elt_ty : elt comparable_ty
  module OPS : S.SET with type elt = elt
  val boxed : OPS.t
  val size : int
end

type 'elt set = (module Boxed_set with type elt = 'elt)

我从未听说过像type a = (module B) 这样的语法。所以我打开一个顶级 OCaml 解释器并使用模块 batteries 重现类似的用法。以下代码是我复制的日志。

$ ocaml
        OCaml version 4.07.1

# #use "topfind";;
- : unit = ()
Findlib has been successfully loaded. Additional directives:
  #require "package";;      to load a package
  #list;;                   to list the available packages
  #camlp4o;;                to load camlp4 (standard syntax)
  #camlp4r;;                to load camlp4 (revised syntax)
  #predicates "p,q,...";;   to set these predicates
  Topfind.reset();;         to force that packages will be reloaded
  #thread;;                 to enable threads

- : unit = ()

# #require "batteries";;
[...]: loaded

# type 'elt set = (module BatSet.S with type elt = 'elt);;
type 'elt set = (module BatSet.S with type elt = 'elt)

这种奇怪的类型定义确实有效,但我卡在这里。模块本身如何成为类型?如何创建一个类型为'elt set 的值,如let v : int set = (...)?有什么关键字可以调用这样的类型吗?

[*] https://gitlab.com/tezos/tezos/blob/master/src/proto_alpha/lib_protocol/script_typed_ir.ml,提交哈希:86b5227f7efd8aa78fcc427776920480c6c0e780

【问题讨论】:

    标签: types module ocaml


    【解决方案1】:

    这是具有约束的第一类模块的类型:https://caml.inria.fr/pub/docs/manual-ocaml/manual028.html

    此类型可用于将模块打包到值中:

    let int_set = ((module BatSet.Make(Int)): int set);;
    

    然后可以将这些值解包到一个模块中,例如,我可以使用它来定义一个unique_sorted 函数:

    let unique_sorted (type a) ((module MySet): a set) list =
      let set = List.fold_left (fun set x -> MySet.add x set) MySet.empty list in
      MySet.elements set
    let test = assert( unique_sorted int_set [4;0;1;2;2] = [0;1;2;4] )
    

    【讨论】:

      【解决方案2】:

      (module M) 这样的类型是一等模块的类型。

      您可以简单地通过定义具有正确类型的模块来生成这种类型的值。

      这是我用来测试的一个简单示例:

      # module type B = sig type elt end;;
      module type B = sig type elt end
      # type 'elt b = (module B with type elt = 'elt);;
      type 'elt b = (module B with type elt = 'elt)
      # module X = struct type elt = int end;;
      module X : sig type elt = int end
      # (module X : B with type elt = int);;
      - : (module B with type elt = int) = <module>
      

      最后一行显示module X 被视为一个值(一级模块)。

      现在,确实,这个值的类型为int b

      # ((module X : B with type elt = int) : int b);;
      - : (module B with type elt = int) = <module>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-06-03
        • 1970-01-01
        • 1970-01-01
        • 2014-03-01
        • 2018-08-19
        • 2022-01-18
        • 1970-01-01
        相关资源
        最近更新 更多