Functional programming 将模块及其实例作为OCaml函数的参数

Functional programming 将模块及其实例作为OCaml函数的参数,functional-programming,scope,ocaml,Functional Programming,Scope,Ocaml,我想写一个函数,它接受实现特定签名的模块和与这些模块类型相同的实例,但显然我不能这样做,因为与模块范围相关的问题(模块及其实例都是参数,因此实例不知道模块的类型) 以下是一个例子: 设f(类型a)(模块M:Set.S,类型elt=a)(pr:a->unit)(M:M.t)= 国际热核聚变实验堆;; 其中,M是带有a类型元素的集合模块,pr可以是a类型元素的打印机。 以及由此产生的错误信息(我不认为这是非常清楚的): 我试图解决这个问题,因为考虑到这个问题是由参数的范围只覆盖函数体引起的,所以我

我想写一个函数,它接受实现特定签名的模块和与这些模块类型相同的实例,但显然我不能这样做,因为与模块范围相关的问题(模块及其实例都是参数,因此实例不知道模块的类型)

以下是一个例子:

设f(类型a)(模块M:Set.S,类型elt=a)(pr:a->unit)(M:M.t)=
国际热核聚变实验堆;;
其中,
M
是带有
a
类型元素的集合模块,
pr
可以是
a
类型元素的打印机。 以及由此产生的错误信息(我不认为这是非常清楚的):

我试图解决这个问题,因为考虑到这个问题是由参数的范围只覆盖函数体引起的,所以我将最后一个参数放在函数体中,如下所示:

let f (type a) (module M: Set.S with type elt = a) (pr : a -> unit) =
  fun (m : M.t) ->
    M.iter pr m;;
但错误消息仍然存在:

Line 2, characters 7-16:
Error: This pattern matches values of type M.t
       but a pattern was expected which matches values of type 'a
       The type constructor M.t would escape its scope
那么有没有办法做到这一点呢?

OCaml核心语言(模块系统之外)不是依赖类型的。在幻想语法中,函数的类型为function
(模块M:Set.S,类型为elt='a)->('a->unit)->M.t
)。在这种类型中,
M
是一个值,因此该类型是依赖类型的,不能在OCaml中实现

在您的情况下,可以通过使用约束限制作为参数接受的模块类,使类型不依赖

设f(类型a和类型t)(模块M:Set.S,类型elt=a和类型t=t)
pr m=m.iter pr m
模块字符串\u set=set.Make(字符串)
让()=f(模块字符串集)忽略字符串集。空
另一种可能的解决方案是将值与第一类模块及其存在量化一起存储:


模块类型=sig
a型
模块Impl:Set.S,类型elt=a
val值:Impl.t
结束
设g(a型)(模块P:填充a型=a)
pr=P.Impl.iter pr P.value
但对于更复杂的函数,除了在模块级使用函子之外,没有其他选择

旁白:如果您想知道为什么在上面的第一个变体中,模块类型<代码>代码集>类型为elt=A类型,t= t/t>代码是一个(必要的)限制,考虑这个打包模块:

let random_int_set:(类型为elt=int的模块集.S)=
让我们来比较一下=
如果Random.int 3>1,则Stdlib.compare
其他(乐趣x y->Stdlib.compare y x)
在里面
让模块S=Set.Make(结构类型t=int let compare=compare end)位于
(模块S)
这里,集合类型基于随机
比较
函数。因此,集合的类型与所有其他
set
s不兼容。因此,只能使用具有压缩值的模块:

module P = struct
  type a = int
  module Impl = (val random_int_set)
  let value = Impl.empty
end
let () = g (module P) ignore
module P = struct
  type a = int
  module Impl = (val random_int_set)
  let value = Impl.empty
end
let () = g (module P) ignore