2016-02-03 30 views
9

Tôi đang cố gắng tìm ra cách viết hàm tùy thuộc vào một mô-đun có kiểu tham số nhưng tôi không thể tìm thấy bất kỳ thứ gì tương tự ở bất kỳ đâu. Tôi đã cố gắng giảm thiểu vấn đề càng nhiều càng tốt và kết thúc với ví dụ giả này.Tham số cục bộ tham số

module type Mappable = sig 
    type 'a t 
    val map : ('a -> 'b) -> 'a t -> 'b t 
end 

let plus (type m) (module M : Mappable with type 'a t = 'a m) (xs : int m) = 
    M.map (fun x -> x + 1) xs 

sản lượng lỗi Error: Syntax error: module-expr expected.

Nếu tôi rơi 'a, tôi sẽ gặp phải lỗi sau.

Error: In this `with' constraint, the new definition of t 
     does not match its original definition in the constrained signature: 
     Type declarations do not match: type t is not included in type 'a t 
     They have different arities. 

Cú pháp chính xác để thực hiện việc này là gì?

Trả lời

7

Tôi tin rằng những gì bạn muốn làm ở đây là không thể trong OCaml 4.02.3. Hãy xem một phiên bản đơn giản mà không có loại biến:

module type Mappable = sig 
    type t 
    val map : ('a -> 'b) -> t -> t 
end 

let plus (type m) (module M : Mappable with type t = m) (xs : m) = 
    M.map (fun x -> x + 1) xs 

Trên đây là phân typ và plus có các loại sau đây:

val plus : (module Mappable with type t = 'm) -> 'm -> 'm 

loại m trong định nghĩa của nó là trừu tượng cho một biến 'm.

Bây giờ, hãy quay lại mã ban đầu của bạn và nghĩ rằng loại plus là nghĩa vụ phải có. Kể từ khi bạn đang cố gắng trừu tượng m bởi (type m), nó phải là:

val plus : (module Mappable with type 'a t = 'a 'm) -> 'a 'm -> 'a 'm 

Thật không may, OCaml không hỗ trợ đa hình kinded cao mà cho phép hình thức loại 'a 'm. Có vẻ như việc gõ mô-đun lớp đầu tiên được thực hiện một cách cẩn thận để không giới thiệu nó.

Bạn có thể xem bài viết ngắn sau đây giải thích trạng thái hiện tại (không may) của tính đa hình cao hơn trong OCaml. Điều này lý giải một cách giải quyết: làm thế nào để mã hóa nó trong khuôn khổ OCaml hiện tại với một chi phí coersions rõ ràng:

https://ocamllabs.github.io/higher/lightweight-higher-kinded-polymorphism.pdf

Tôi chưa bao giờ cố gắng của bản thân mình nhưng cách giải quyết tương tự có thể được áp dụng cho ví dụ của bạn.

6

Nó không phải là có thể trong OCaml, như các loại khăn không phải là một kiểu mô-đun thông thường hạn chế, nhưng một đặc biệt syntactic construct, điều đó không cho phép các loại đa hình:

Gói kiểu lớp cú pháp xuất hiện trong biểu thức kiểu (mô-đun kiểu gói) và trong các biểu mẫu được chú thích thể hiện một tập con của các kiểu mô-đun. Tập hợp con này bao gồm các loại mô-đun được đặt tên với các ràng buộc tùy chọn của một dạng giới hạn: chỉ có thể chỉ định các kiểu không tham số.

Một cách giải quyết thông thường sẽ là để tạo ra một mô-đun mà gắn bó với tất cả các biến kiểu với các loại bê tông:

module type Mapper = sig 
    type a 
    type b 
    type src 
    type dst 
    val map : (a -> b) -> src -> dst 
end 

let plus (type src) (type dst) 
    (module M : Mapper with type dst = dst 
         and type src = src 
         and type a = int 
         and type b = int) (xs : src) : dst = 
    M.map (fun x -> x + 1) xs 

Trong ví dụ cụ thể của bạn, không có nhu cầu để ràng buộc 'a'b, vì chúng về cơ bản không được sử dụng, vì vậy nó có thể được đơn giản hóa để:

module type Mapper = sig 
    type src 
    type dst 
    val map : ('a -> 'b) -> src -> dst 
end 

let plus (type src) (type dst) 
    (module M : Mapper with type dst = dst 
         and type src = src) (xs : src) : dst = 
    M.map (fun x -> x + 1) xs 

Tất nhiên, điều này là rất hạn chế, nhưng đây là những gì có thể trong ngày.

2

functors Nếu bạn muốn vượt qua các module chức năng, bạn nên sử dụng thay vì:

module F (M : Mappable) = struct 
    let plus xs = M.map (fun x -> x + 1) xs 
end 
Các vấn đề liên quan