2012-02-15 32 views
6

Tôi đang xây dựng hai thư viện trong OCaml chứa cùng loại biến thể. Các chi tiết của biến thể không phải là quá quan trọng, khác hơn là nó thực sự là lớn, và nó sẽ được gây phiền nhiễu để viết các chức năng chuyển đổi bằng tay cho nó. (Nó thực sự là bfd_architecture liệt kê chuyển đổi từ C bằng cách sử dụng ocamlidl).Loại tương đương OCaml

Tôi hiện đang viết chương trình bằng hai thư viện. Đặc biệt, tôi đang gọi A.f trả về giá trị của A.variant_type và tôi cần phải sử dụng giá trị đó trong cuộc gọi đến B.g, giá trị của B.variant_type là đầu vào.

Có cách nào để nói với OCaml rằng A.variant_type và B.variant_type thực sự là cùng loại hay không và do đó, nó có thể chuyển đổi giá trị từ cái này sang giá trị khác? Các thư viện độc lập, vì vậy chúng không nên tham chiếu lẫn nhau. Ngay bây giờ tôi đang sử dụng Obj.magic để thực hiện chuyển đổi, nhưng đây là một hack.

+0

tại sao bạn không thể, như ygrek gợi ý, có hai thư viện chia sẻ cùng một loại biến thể, thay vì tạo hai biến thể khác nhau có cùng cấu trúc? – gasche

+4

Nói cách khác, hãy đặt loại biến thể thành mô-đun thứ ba và sử dụng nó trong các mô-đun khác. Bạn có thể 'mở' module để làm cho việc đặt tên nhẹ hơn. –

Trả lời

1

Bạn không cần phải sử dụng Obj.magic, mặc dù bạn phải sử dụng một số "kỳ diệu",

external convertAB : A.t -> B.t = "%identity" 
external convertBA : B.t -> A.t = "%identity" 

là đủ để thực hiện chuyển đổi. Tất nhiên, tôi hiểu mối quan tâm của bạn; cả hai loại phải giống hệt nhau, bạn sẽ xử lý các lỗi thời gian chạy. Nếu có thể và có liên quan, chuyển đổi các biến thể đó thành Polymorphic Variants sẽ giải quyết được sự cố.

+1

Sử dụng các biến thể đa hình là một giải pháp tốt cho vấn đề chung. Trong trường hợp của tôi, tôi đang sử dụng ocamlidl để tạo ra loại biến thể và tôi không thấy tùy chọn buộc nó tạo ra các biến thể đa hình. –

+2

Tôi chắc chắn bạn biết điều này, nhưng sử dụng '"% identity "' hoàn toàn giống như sử dụng 'Obj.magic' (" giống hệt nhau "trong thực tế). Bạn thực sự muốn tránh chúng nếu có thể. –

+0

Ồ đúng rồi. Tôi chỉ nhìn vào nguồn. Tốt để biết. – nlucaroni

8

Tôi tin rằng không có cách nào sạch trừ khi các thư viện này có một số phụ thuộc chung định nghĩa loại này (tức là cùng một mô-đun được tham chiếu từ cả hai thư viện tại thời điểm xây dựng).

3

Nếu bạn thực sự muốn loại biến thể xuất hiện trong cả hai thư viện, bạn cũng có thể bắt buộc kiểm tra xem chúng có tương đương hay không. Trong thư viện thứ hai, bạn có thể viết:

type t = OtherLib.t = | A | B | C | ... 

Điều này sẽ làm cho trình biên dịch xác minh rằng OtherLib.t = A | B | C | ... và làm cho hai loại bằng nhau. Tôi không nghĩ rằng nó thực sự giải quyết trường hợp của bạn, vì bạn có thể không muốn thay đổi một trong hai thư viện.

Tôi thường làm điều đó khi tôi muốn giữ các phiên bản khác nhau của một loại (vì chúng được lưu trong các tệp mà tôi muốn đọc sau) và tôi muốn mỗi phiên bản rõ ràng các nhà xây dựng trong khi vẫn giữ sự tương đương khi có thể với Phiên bản hiện tại.

+0

Đó là bực bội gần với những gì cần thiết. Thật đáng ngạc nhiên khi bạn có thể làm điều đó, nhưng không thể gõ t = Firstlib.t = Secondlib.t. –