2010-10-30 22 views
9

Giả sử chúng ta định nghĩa một GADT để so sánh các loại:Runtime so sánh các loại cho nâng cấu trúc dữ liệu đa hình thành GADTs

data EQT a b where 
    Witness :: EQT a a 

là nó sau đó có thể tuyên bố một hàm eqt với chữ ký loại sau đây:

eqt :: (Typeable a, Typeable b) => a -> b -> Maybe (EQT a b) 

... mà eqt xy đánh giá để Chỉ cần chứng nếu typeof x == t ypeOf y --- và cách khác là Không có gì?

Chức năng eqt sẽ giúp bạn có thể nâng cấu trúc dữ liệu đa hình thông thường thành GADT.

Trả lời

11

Vâng. Dưới đây là một cách:

Đầu tiên, loại kiểu bình đẳng.

data EQ :: * -> * -> * where 
    Refl :: EQ a a -- is an old traditional name for this constructor 
    deriving Typeable 

Lưu ý rằng bản thân nó có thể được tạo thành thể hiện của Typeable. Đó là chìa khóa. Bây giờ tôi chỉ cần có được bàn tay của tôi trên Refl Tôi cần, như thế này.

refl :: a -> EQ a a 
refl _ = Refl 

Và bây giờ tôi có thể cố gắng để biến (refl :: Eq một a) vào một cái gì đó kiểu (Eq a b) bằng cách sử dụng nhà điều hành đúc Data.Typeable của. Điều đó sẽ chỉ hoạt động khi a và b bằng nhau!

eq :: (Typeable a, Typeable b) => a -> b -> Maybe (EQ a b) 
eq a _ = cast (refl a) 

Công việc khó khăn đã được thực hiện.

Có thể tìm thấy các biến thể khác về chủ đề này trong thư viện Data.Witness, nhưng toán tử cast Data.Typeable là tất cả những gì bạn cần cho công việc này. Đó là gian lận, tất nhiên, nhưng một cách gian lận đóng gói an toàn.

+0

Thật gọn gàng! Cảm ơn. –

+0

Được đóng gói an toàn miễn là không ai tạo ra một phiên bản 'Data.Typeable' không chính xác trên một thứ gì đó. ('deriving Typeable' luôn an toàn.) –

+0

Lưu ý rằng những ngày này' eq' có sẵn trong mô-đun 'Data.Typeable' là [' eqT'] (https://hackage.haskell.org/package/base-4.9) .0.0/docs/Data-Typeable.html # v: eqT) –

Các vấn đề liên quan