2012-07-16 27 views
8

Tổng số người mới ở đây, đang gặp khó khăn.Haskell: Làm thế nào tôi có thể định nghĩa một loại lớp cho các bộ?

Tôi đang cố xác định loại loại cho tập hợp. Đối với trường hợp này, nó sẽ chỉ yêu cầu định nghĩa 'tồn tại'. 'tồn tại' sẽ lấy một tập hợp và chức năng trên một mục đã đặt và trả lại một boolean. Làm thế nào tôi có thể xác định điều đó trong Haskell?

Sau đây có phải là đúng hướng không? Vì vậy, có là định nghĩa kiểu lớp và một thực hiện của bộ với danh sách, mà 'tồn tại' trả về true cho bây giờ ..

-- Set.hs -- 

class Set a b where 

    exists :: a -> (b -> Bool) -> Bool 


-- ListSet.hs -- 

instance Set ListSet a where 

    exists a f = True 

-

(kết quả: Quá nhiều tham số cho lớp 'Set ')

Trả lời

13

Bạn có thể thực hiện theo cách này, với đủ tiện ích mở rộng. Ít nhất, bạn sẽ cần nhiều lớp kiểu tham số. Tuy nhiên, nó sẽ rất khó chịu khi sử dụng: bạn sẽ cần phải chỉ định các chữ ký rõ ràng trên khắp nơi. Một cách để khắc phục sự cố đó là giới thiệu một sự phụ thuộc chức năng (sử dụng một phần mở rộng khác):

class Set a b | a -> b where 
    exists :: a -> (b -> Bool) -> Bool 

Điều này nói rằng bạn cũng biết loại phần tử đó. Tuy nhiên, có một cách đơn giản hơn mà làm việc mà không cần bất kỳ phần mở rộng:

class Set f where 
    exists :: f a -> (a -> Bool) -> Bool 

Ở đây, lớp loại dao động so với các loại cao kinded, đó là một thủ thuật gọn gàng và khó khăn để đến với một mình nếu bạn chưa bao giờ nhìn thấy nó trước!

+1

Tất nhiên, thuộc tính thứ hai yêu cầu loại phần tử là tham số kiểu cuối cùng cho loại thiết lập - không phải lúc nào cũng có thể, như nếu bạn muốn tạo một cá thể cho 'a -> Bool'. Mặt khác, các gia đình có liên quan sẽ giải quyết được điều đó. – Carl

+2

Cảm ơn! Tôi đã làm việc theo cách thứ hai! Tôi phải thừa nhận rằng tôi không hoàn toàn hiểu những gì xảy ra ở đó, nhưng hy vọng nó cho thấy chính nó với tôi ... – tero

7

Daniel Wagner đã đưa ra câu trả lời hoàn hảo về những gì bạn đang cố gắng làm. Tôi chỉ muốn thêm một điểm về lỗi của bạn - Too many parameters for class 'Set'. Điều này có nghĩa là bạn không bật tiện ích mở rộng GHC tương ứng - MultiParamTypeClasses. Bạn có thể làm điều đó bằng cách chỉ định loại nhận xét đặc biệt ở đầu tệp nguồn của mình:

{-# LANGUAGE MultiParamTypeClasses #-} 
-- 
-- Your source code here 
-- 

Sau đó, bạn sẽ có thể biên dịch mã của mình.

Một tính năng Haskell khác được đề cập trong câu trả lời của Daniel cũng yêu cầu bật phần mở rộng nhất định, cụ thể là FunctionalDependencies (đây là điều .. | a -> b .. kỳ lạ bên trong khai báo lớp loại). Bạn có thể bật nhiều phần mở rộng cùng một lúc sử dụng dấu phẩy, như thế này:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} 

bình luận của Carl đề cập một phần mở rộng, TypeFamilies, mà cũng có thể cung cấp phương tiện cho những gì bạn đang cố gắng làm (lớp chung của các loại bộ hoặc khác loại bộ sưu tập). Bạn có thể đọc về nó ở đây: http://www.haskell.org/haskellwiki/Type_families.

+0

Tôi quản lý để làm điều đó cũng với phương pháp phụ thuộc chức năng. Tuy nhiên, tôi cũng phải bao gồm phần mở rộng 'FlexibleInstances'. – tero

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