Điều quan trọng cần hiểu ở đây là OCaml thực hiện suy luận kiểu theo cách tổng hợp, tức là, đầu tiên sẽ suy ra loại struct ... end
và chỉ sau đó nó sẽ khớp với các loại suy ra so với sig ... end
để xác minh rằng cấu trúc thực sự thực hiện chữ ký.
Ví dụ, nếu bạn viết
module Monkey : sig val f : int -> int end =
struct
let f x = x
end
sau đó OCaml sẽ được hạnh phúc, vì nó sẽ thấy rằng f
có một kiểu đa hình 'a -> 'a
có thể được chuyên biệt hóa cho loại yêu cầu int -> int
. Bởi vì sig ... end
làm cho Monkey
mờ, tức là chữ ký ẩn việc triển khai, nó sẽ cho bạn biết rằng f
có loại int -> int
, mặc dù việc triển khai thực tế có loại đa hình.
Trong trường hợp cụ thể của bạn, OCaml đầu tiên cho rằng g
có loại 'a -> 'a
và sau đó loại h
cũng là 'a -> 'a
. Vì vậy, kết luận rằng cấu trúc có loại
sig val g : 'a -> 'a val h : 'a -> 'a end
Tiếp theo, chữ ký được khớp với chữ ký nhất định. Bởi vì một chức năng của loại 'a -> 'a
có thể được chuyên biệt để int -> int
cũng như string -> string
OCaml kết luận rằng tất cả là tốt. Tất nhiên, toàn bộ điểm sử dụng sig ... end
là làm cho cấu trúc mờ đục (việc triển khai bị ẩn), đó là lý do tại sao số dư làm không phơi bày loại đa hình g
và h
.
Dưới đây là một ví dụ khác trong đó cho thấy cách OCaml hoạt động:
module Cow =
struct
let f x = x
let g x = f [x]
let a = f "hi"
end
module Bull : sig
val f : int -> int
val g : 'b * 'c -> ('b * 'c) list
val a : string
end = Cow
Câu trả lời là
module Cow :
sig
val f : 'a -> 'a
val g : 'a -> 'a list
val a : string
end
module Bull :
sig
val f : int -> int
val g : 'a * 'b -> ('a * 'b) list
val a : string end
end
Nguồn
2012-06-19 21:03:19
câu trả lời của bạn là hoàn toàn chính xác. – gasche
Tuyệt vời, cảm ơn! :-) –