0

1) Suppose there is a module

module Int_Sig_1 =
struct
let x = 1
end
;;

2) and an explicit signature of this module

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

3) and i create a first-class module based on the above module and module type

let int_sig_1 = (module Int_Sig_1:INT_SIG)

4) Now i create another module with no explicit signature but same inferred signature as above

module Int_Sig_2 =
struct
let x =2
end
;;

5) As written in Chapter 10 of the book Real World OCAML "The module type doesn't need to be part of the construction of a first-class module if it can be inferred", i try to create a second first class module using the above module but with no explicit module type

let a2 = (module Int_Sig_2);;

I get the following error

Error: The signature for this packaged module couldn't be inferred.

6) then i try to do the same as above in 5, but this time I put the first class module with no module type being create as an element of a list, where the head of the list is a first class module that was created out of an explicit signature in 3 above.

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

My question is why 5 above gives me an error and 6 does not fail ?

4

1 回答 1

3

(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. 

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

于 2017-08-06T15:06:51.783 回答