2012-06-19 28 views
5

nó là khá lạ rằng đoạn mã ocaml này được đánh máy tốt bởi các toplevel. Nhìn vào cấu trúc, nếu g là loại int-> int như được hiển thị trong toplevel, phần h x = g x của cấu trúc sẽ không thể nhận được loại thống nhất. Vì vậy, bất kỳ ai có thể làm rõ một chút?Một ví dụ lạ về việc gõ vào Ocaml

module Mymodule : sig 
    val h:int ->int 
    val g: string-> string 
end = struct 
    let g x = x 
    let h x = g x 
end 

Đây là phản ứng của topelevel:

module Mymodule : sig val h : int -> int val g : string -> string end 

Trả lời

7

Đ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 gh.

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 
8

Tôi muốn nói rằng string -> string gõ không được áp dụng cho g cho đến khi nó xuất từ các mô-đun. Bên trong mô-đun (vì bạn không cho nó loại), nó có loại 'a -> 'a. (Disclaimer: Tôi không phải là một chuyên gia mô-đun, cố gắng tìm hiểu mặc dù.)

+0

câu trả lời của bạn là hoàn toàn chính xác. – gasche

+0

Tuyệt vời, cảm ơn! :-) –