【问题标题】:Why is it impossible to include module type from functor parameter module into module type in resulting module of functor?为什么不可能将函子参数模块中的模块类型包含到函子的结果模块中的模块类型中?
【发布时间】:2020-12-27 08:28:08
【问题描述】:

OCaml 不提供直接通过仿函数创建模块类型的能力。但是,它允许对嵌套模块类型进行一些操作。所以,我可以使用参数中的模块类型来绑定结果中的模块类型:

module CONTAINER = struct
  module type S = sig
    val a : int
  end
end

module COPY (CONTAINER : sig module type S end) = struct
  module type S = CONTAINER.S
end 

module type S_FROM_CONTAINER = COPY(CONTAINER).S
    

S_FROM_CONTAINER 不是抽象的。申请S_FROM_CONTAINER需要提供a

(*
module Impl : S_FROM_CONTAINER = struct
end 

> Error: Signature mismatch:
> Modules do not match: sig end is not included in S_FROM_CONTAINER  
> The value `a' is required but not provided
*)

module Impl : S_FROM_CONTAINER = struct
  let a = 42
end 

另外,我可以使用来自CONTAINERS 作为生成模块中模块类型中的一种模块:

module AS_TYPE_OF_IMPL (CONTAINER : sig module type S end) = struct
  module type S = sig
    module Impl : CONTAINER.S 
  end
end 

module type IMPL_CONTAINER_S = 
  AS_TYPE_OF_IMPL(CONTAINER).S 

IMPL_CONTAINER_S 中的Impl 模块也不是抽象模块类型:

(* module ImplContainer : IMPL_CONTAINER_S = struct
     module Impl = struct end
   end

> Error: Signature mismatch:
> Modules do not match:
>   sig module Impl : sig end end
> is not included in
>   IMPL_CONTAINER_S
> In module Impl:
> Modules do not match: sig end is not included in CONTAINER.S
> In module Impl:
> The value `a' is required but not provided
*)

module ImplContainer : IMPL_CONTAINER_S = struct
  module Impl = struct let a = 42 end
end

没关系。我认为这是一个强大的工具。但我发现了一个让我难过的局限。不可能将此模块类型包含到另一个模块类型中。

module EXTEND_S (CONTAINER : sig module type S end) = struct
  module type S = sig
    include CONTAINER.S
    val extention : int
  end
end

或者

module AS_PART_OF_IMPL (CONTAINER : sig module type S end) = struct
  module type S = sig
    module Impl : sig
      include CONTAINER.S
      val extention : int
    end 
  end 
end

include CONTAINER.S
^^^^^^^^^^^
错误:此模块类型不是签名

为什么我不能这样做?对我来说,这看起来像是一些差距,不仅在编译器上,而且在语言概念上也是如此。我想了解什么?

【问题讨论】:

    标签: module ocaml functor


    【解决方案1】:

    简而言之,include 不是模块类型系统的一部分,它们通过内联签名的内容来处理签名。在模块系统中添加include 表达式并不是那么简单,因为在任何上下文中都不能包含任何模块类型。例如考虑:

    module F(X:sig module type x module type y end) = struct
      module type result = sig 
        include x
        include y
      end
    end
    

    并不总是有效的。例如,考虑

    module type x = sig
      type t
      val x: t
    end
    module type y = sig
      type t
      val y: t
    end
    

    然后

    module type t = sig
      include x
      include y
    end
    

    产生错误

    Error: Illegal shadowing of included type t/863 by t/865
          Line 2, characters 2-11:
            Type t/863 came from this include
          Line 3, characters 2-10:
            The value x has no valid type if t/863 is shadowed
    

    因此include s 并不总是有效的,并且要包含抽象类型模块需要改进模块类型系统以捕捉这种情况。

    此外,具有动态数量的运行时组件的模块类型将需要不同的编译方案,因为查询模块内的路径不能再简化为查询块中统计上已知的索引。

    【讨论】:

      猜你喜欢
      • 2019-03-21
      • 2011-08-27
      • 1970-01-01
      • 1970-01-01
      • 2018-07-02
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多