【问题标题】:OCAML first class modules signature inferenceOCAML 一级模块签名推断
【发布时间】:2018-01-13 22:39:06
【问题描述】:

1) 假设有一个模块

module Int_Sig_1 =
struct
let x = 1
end
;;

2) 以及该模块的显式签名

module type INT_SIG =
sig
val x:int
end
;;

3) 我根据上面的模块和模块类型创建了一个一流的模块

let int_sig_1 = (module Int_Sig_1:INT_SIG)

4) 现在我创建另一个没有显式签名但推断签名与上面相同的模块

module Int_Sig_2 =
struct
let x =2
end
;;

5) 正如 Real World OCAML 一书的第 10 章所写的“如果可以推断,模块类型不需要成为第一类模块构造的一部分”,我尝试先创建第二个使用上述模块但没有显式模块类型的类模块

let a2 = (module Int_Sig_2);;

我收到以下错误

错误:无法推断此打包模块的签名。

6) 然后我尝试在 5 中执行与上面相同的操作,但这次我将创建的 没有模块类型的第一类模块作为列表的元素,其中的头该列表是由上面 3 中的显式签名创建的第一类模块。

let int_sig= [int_sig_1;(module Int_Sig_2)];;
val int_sig : (module INT_SIG) list = [<module>; <module>] ;;

我的问题是为什么上面的 5 给了我一个错误,而 6 没有失败?

【问题讨论】:

    标签: module ocaml type-inference signature first-class


    【解决方案1】:

    (5) 的问题在于,通常可以推断出多种模块类型。在您的示例中,至少有两种有效的模块类型可用于打包 Int_Sig_2

     module type empty = sig end
     module type with_x = sig val x:int end
    

    换句话说,两者都

     let a2 = (module Int_Sig_2: empty)
     let a2_bis = (module Int_Sig_2:with_x)
    

    有效。因此,在这种情况下,类型检查器不会尝试推断模块类型。

    相反,在您的示例 (6) 中,列表的类型由其第一个元素确定,其类型为 (module INT_SIG_2),因此类型检查器可以使用此信息来推断第二个元素的预期类型列表中的(module INT_SIG_2)。然而,颠倒这两个元素会产生类型错误。换句话说,这很好:

     [(module struct let x = 2 end: with_x); (module struct let x = 1 end)]
    

    然而,反过来产生

    [(module struct let x=2 end); (module struct let x = 3 end:with_x)];;
    Error: The signature for this packaged module couldn't be inferred. 
    

    这是因为类型检查器具有从左到右的偏差,并且首先键入列表的第一个元素。

    【讨论】:

    • 感谢您清晰明确的回答,我可以问您一个后续问题吗?
    • 当然,不要问。
    • 感谢您的特权。假设我有 1) 模块类型 MOD_SIG = sig type t val min:t
    • 1) 模块类型 MOD_SIG = sig 类型 t val min val max 2) 模块 MOD_UINT8 = 结构类型 t = int32 let min = Int32.of_int 0 let max = Int32.of_int 255 end;; 3) 模块 MOD_UINT32 = 结构类型 t = int64 let min = Int64.zero let max = Int64.of_int 4294967295 end ;; 4) 2和3的一级模块 let uint_8 = (module MOD_UINT8:MOD_SIG) ;;让 uint_32 = (模块 MOD_UINT32:MOD_SIG);; 5) 我想在匹配 M.t 和 Int32 -> "Int32" | 中写一些类似 let module M=(val m:MOD_SIG) 的东西Int64 -> "Int64" 我该怎么做这样的事情?
    • 你不能,在 OCaml 中,类型会在运行时被擦除。因此,绝对不可能在类型上进行匹配。这里的解决方案是在模块结构中添加一个let name = "Int[N]"。如果您在这个方向上有更多问题,您可能应该提出新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多