2012-01-16 18 views
8

Tôi phải xác định loại loại Truthy có chứa phương thức true chuyển đổi phiên bản loại thành giá trị Bool.Làm thế nào để viết một thể hiện cho tất cả các loại trong lớp loại khác?

loại của tôi khai báo lớp:

class Truthy a where 
    true :: a -> Bool 

Tiếp theo, tôi phải xác định các trường hợp của lớp này với nhiều loại khác nhau, bao gồm danh sách và các loại số. Tôi đã làm nó cho danh sách và Int s, nhưng có cách nào để làm điều đó cho tất cả các loại số cùng một lúc?

Dựa trên tuyên bố Int tôi:

instance Truthy Int where 
    true = (/=) 0 

Tôi đã thử thêm kiểu lớp hạn chế, nhưng nó không hoạt động:

instance (Num a) => (Truthy a) where 
    true = (/=) 0::a 

Nếu có một cách để làm điều này tương tự như những gì tôi đã có trong tâm trí, hay tôi nên chỉ xác định nó cho từng loại số một cách riêng biệt?

+0

"hoặc tôi chỉ nên xác định nó cho từng loại số riêng biệt?" - trong một từ ** Có **. Mục tiêu thiết kế của các lớp loại là cho phép quá tải trên cơ sở mỗi loại. Với các phần mở rộng, có thể xác định được các trường hợp "overreaching" nhưng chúng thường là một lỗ hổng thiết kế. –

+0

có thể trùng lặp của [Khai báo tất cả các cá thể của một kiểu chữ là một kiểu chữ khác mà không sửa đổi các khai báo lớp gốc] (http: // stackoverflow.com/questions/8461029/khai báo-tất cả các trường hợp-of-a-typeclass-là-in-khác-typeclass-mà không sửa đổi) –

Trả lời

10

Điều này có thể không giúp ích cho bài tập về nhà, nhưng bạn thực sự có thể viết tuyên bố như vậy. Bạn chỉ cần kích hoạt -XFlexibleInstances để làm như vậy. Ít nhất trong GHC, bạn có thể làm điều này bằng cách đặt một pragma ở phía trên cùng của tập tin của bạn:

{-# LANGUAGE FlexibleInstances #-} 

Nếu bạn nhìn kỹ vào thông báo lỗi bạn có, nó nói cái gì đó như "Sử dụng -XFlexibleInstances nếu bạn muốn vô hiệu hóa điều này.

Trong trường hợp này, bạn cũng sẽ cần phải kích hoạt UndecideableInstancesOverlappingInstances:

{-# LANGUAGE FlexibleInstances, UndecideableInstances, OverlappingInstances #-} 

Bạn cần FlexibleInstances vì tiêu chuẩn Haskell không cho phép trường hợp trong bất kỳ hình thức mà loại biến xuất hiện nhiều lần vào đầu . Điều này là hoàn toàn tốt - Tôi là một trong những phần mở rộng phổ biến nhất được sử dụng (theo this question).

Bạn cần UndecideableInstances vì khai báo cá thể của bạn có thể khiến trình kiểm tra loại lặp lại mãi mãi. Tôi nghĩ rằng việc sử dụng UndecideableInstances sẽ ngăn chặn điều này bằng cách giới hạn mức độ sâu sẽ kiểm tra khi cố gắng giảm phiên bản. Điều này thường - bao gồm trong trường hợp này - tốt, nhưng về mặt lý thuyết có thể làm cho dù một chương trình cụ thể vượt qua các loại kiểm tra thực hiện phụ thuộc. Tuy nhiên, nó sẽ làm việc trong trường hợp của bạn.

Vì hammar chỉ ra, bạn cần bật OverlappingInstances vì "ngữ cảnh" của cá thể là bỏ qua khi kiểm tra xem chúng có trùng lặp hay không. Ngữ cảnh là bit Num a trong trường hợp này. Vì vậy, các trường hợp - để kiểm tra xem nó có trùng lặp hay không - được đọc là instance Truthy a... và trùng lặp với mọi thứ. Với kích hoạt OverlappingInstances, bạn chỉ cần có một phiên bản cụ thể nhất để làm việc này.

+0

Tôi thấy rằng trong nhật ký lỗi. Thật tuyệt vời khi nhận được một lời giải thích về lý do tại sao tôi cần phải kích hoạt thêm bất kỳ thứ gì để có được điều này để biên dịch, hoặc tại leas, nơi tôi có thể đọc về điều đó. Ngoài ra, đó là cách duy nhất để làm những gì tôi muốn? – penelope

+0

Về cơ bản, báo cáo Haskell 98 đã xác định rằng các khai báo lớp phải là "đơn giản". Vì vậy, * tiêu chuẩn * Haskell không cho phép phong cách bạn đã cố gắng sử dụng (trừ khi nó thay đổi trong năm 2010?). Tuy nhiên, mã bạn viết thực sự hợp lý và có thể triển khai được, vì vậy nó được GHC hỗ trợ; lý do bạn cần pragma là nó không có trong tiêu chuẩn. –

+0

Để biết thêm thông tin mà bạn có thể muốn, bạn có thể đọc về nó trong tài liệu [ở đây] (http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/type-class-extensions.html # superclass-rules) và [here] (http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/other-type-extensions.html#flexible-contexts). –

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