2011-01-26 34 views
9

Có cách nào để xác định ràng buộc lớp cho tham số của hàm tạo giá trị không?Chỉ định các ràng buộc của lớp trong các hàm tạo giá trị

Something như thế này:

data Point2D = (Num a) => Point a a 

nên điểm có thể mất bất kỳ đối số miễn là họ thuộc về lớp Num?

+0

Nói chung, tốt hơn nên đặt các ràng buộc loại của bạn khi chúng thực sự cần thiết. Nó không phải là kiểu dữ liệu, nhưng các phương thức mà kiểu Num là cần thiết, vì vậy nó phải được khai báo ở đó. Hệ thống kiểu sẽ xử lý phần còn lại. – amccausl

Trả lời

11

Bạn có thể sử dụng ExistentialQuantification hoặc GADTs, nhưng sẽ không thực hiện những gì bạn muốn. Bạn sẽ không bao giờ có thể làm số học với hai giá trị Point2D. Tất cả những gì bạn biết về nội dung là chúng là một số phiên bản của Num. Bạn đang yêu cầu trình biên dịch loại bỏ tất cả các thông tin khác về chúng. Điều này có nghĩa là bạn đang yêu cầu trình biên dịch loại bỏ bất kỳ thông tin nào có thể có một cặp giá trị cụ thể là Point2D có cùng loại. Và nếu không có thông tin đó, bạn sẽ không thể thực hiện bất kỳ số học nào về các giá trị từ hai số Point2D cùng nhau.

Điều này gần như chắc chắn không phải là điều bạn muốn. Ví dụ, bạn không thể viết hàm distance. Bạn có thể sử dụng những gì có thể cho một loại hạn chế như vậy? Tất cả những gì bạn có thể làm với họ là chuyển đổi nội dung của họ thành String.

Chỉnh sửa:

Tôi nghĩ rằng tôi thấy những gì bạn đang cố gắng làm. Bạn chỉ muốn đảm bảo rằng mọi thứ trong Point2D là một số. Tôi không nghĩ rằng bạn thực sự muốn loại xóa.

Trong trường hợp đó, tôi muốn đi với phiên bản GADT, với một sự thay đổi thực sự quan trọng:

{-# LANGUAGE GADTs #-} 
data Point2D a where 
    Point :: (Num a) => a -> a -> Point2D a 

Kết quả cuối cùng của việc này là bạn chỉ có thể sử dụng các nhà xây dựng Point với hai giá trị của cùng một Ví dụ của Num, nhưng bạn không bị mất loại đó. Hơn nữa, nhờ sử dụng GADTs, mẫu phù hợp trên các nhà xây dựng Point phục hồi bối cảnh Num cho bạn, đó là cơ bản những gì bạn mong đợi.

Nhưng tôi nghĩ điều quan trọng nhất ở đây không phải là loại bỏ nội dung. Làm như vậy làm cho loại cơ bản không thể làm việc với.

+0

Phục hồi ngữ cảnh ví dụ cho các thành viên dữ liệu dường như chỉ hoạt động khi mẫu khớp với kiểu dữ liệu (hoặc với '(Điểm a b)' hoặc với tên trường ghi 'Điểm {x = a, y = b}'). Nhưng có cách nào để có điều này cho các chức năng truy cập trường? Tức là, khi truy cập một 'Point'' p' với một biểu thức như '(x p)'. – Lii

4

Có, nhưng bạn sẽ phải nhận ra rằng ý nghĩa của ràng buộc của bạn khác với các loại chung chung thông thường.

Thông thường, Generics như trong type Foo a = (a, a) nghĩa

cho tất cả các loạia, Foo a bao gồm hai a 's

Tuy nhiên, trong ví dụ của bạn, người ta cần đến cụm từ mà cách khác nhau:

Đối với som e loạia, Point2D bao gồm hai a 's

hoặc

một loại a rằng Point2D gồm

Như vậy, kiểu chung chung không phải là phổ quát (cho tất cả các loại ...), nhưng tồn tại (nó tồn tại một số loại ...). Theo GHC, chúng tôi có thể cho phép điều này thông qua extenstion

{-# ExistentialQuantification #-} 

như được mô tả trong article on the topic này. mã của bạn, sau khi tất cả, là

data Point2D = forall a . Num a => Point a a 
2

Chắc chắn!

này nên làm những gì bạn muốn:

{-# LANGUAGE GADTs #-} 

data Point2D a where 
    Point :: Num a => a -> a -> Point2D a 

p :: Num a => a -> a -> Point2D a 
p = Point 

sumP :: Point2D a -> Point2D a -> a 
sumP (Point a b) (Point c d) = a + b + c + d 

Bạn cũng có thể sử dụng existensials, nhưng sau đó bạn không thể làm bất cứ điều gì với các dữ liệu sau khi mô hình kết hợp trên đó.

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