2010-11-17 30 views
5

Tôi đang cố gắng đại diện cho các cạnh có trọng số. Cuối cùng tôi muốn có OutE là một thể hiện của phương trình và phương trình, với ràng buộc rằng etype là một thể hiện của phương trình và phương trình. tập tin giả sử tôi có sau khi temp.hs:Thêm các ràng buộc kiểu vào ngữ cảnh của khai báo cá thể trong Haskell

data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype} 

applyFunBy accessor ordfun = (\x y -> (ordfun (accessor x) (accessor y))) 

instance Eq (OutE vtype etype) where 
    --(==) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool 
    --(/=) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

khi tôi tải này trong ghci, tôi nhận được các lỗi sau đây:

temp.hs:10:19: 
    Could not deduce (Ord etype) 
     from the context (Eq (OutE vtype etype)) 
     arising from a use of `edgeValue' at temp.hs:10:19-27 
    Possible fix: 
     add (Ord etype) to the context of the instance declaration 
    In the first argument of `applyFunBy', namely `edgeValue' 
    In the expression: applyFunBy edgeValue (==) 
    In the definition of `==': == = applyFunBy edgeValue (==) 

temp.hs:11:19: 
    Could not deduce (Ord etype) 
     from the context (Eq (OutE vtype etype)) 
     arising from a use of `edgeValue' at temp.hs:11:19-27 
    Possible fix: 
     add (Ord etype) to the context of the instance declaration 
    In the first argument of `applyFunBy', namely `edgeValue' 
    In the expression: applyFunBy edgeValue (/=) 
    In the definition of `/=': /= = applyFunBy edgeValue (/=) 
Failed, modules loaded: none. 

Nếu bao gồm các dòng cho chữ ký kiểu cho (==) và (\ =), tôi nhận được:

temp.hs:6:1: 
    Misplaced type signature: 
    == :: 
     (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool 

temp.hs:7:1: 
    Misplaced type signature: 
    /= :: 
     (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool 

Trả lời

5

Bạn hạn chế etypeOrd trong defintion của OutE:

data (Ord etype) => OutE vtype etype = ... 

Nhưng trong Eq Ví dụ, bạn đang thực sự cố gắng để xác định các trường hợp cho bất kỳetype unrestrictedly.

instance Eq (OutE vtype etype) where 

Tất nhiên điều này không làm việc kể từ OutE bản thân chỉ được định nghĩa cho Ord etype s, do đó bạn sẽ có thêm các hạn chế typeclass định nghĩa ví dụ như là tốt.

instance (Ord etype) => Eq (OutE vtype etype) where 

Lưu ý rằng một định nghĩa của một trong hai == hoặc /= là đủ cho typeclass để làm việc.


Lưu ý rằng nó thường dễ dàng hơn và do đó được coi là phong cách tốt hơn không có trở ngại typeclass trên data -types, nhưng chỉ trên trường/phương pháp thật sự yêu cầu các chức năng của typeclass.

Trong nhiều trường hợp, người ta không cần sự ràng buộc và chỉ kết thúc với chữ ký kiểu không cần thiết vụng về.

Ví dụ: một số loại bản đồ được đặt hàng Ord key => Map key value.

Điều gì xảy ra nếu chúng tôi chỉ muốn liệt kê tất cả các khóa? Hoặc nhận được số lượng các yếu tố? Chúng ta không cần những chìa khóa để có Ord cho này, vậy tại sao không chỉ để lại bản đồ không hạn chế với đơn giản

getKeys :: Map key value -> [key] 
getLength :: Map key value -> Int 

và chỉ cần thêm typeclass khi chúng ta thực sự cần nó trong một chức năng như

insert :: Ord key => key -> value -> Map key value 
2
data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype} 

vấn đề đầu tiên: Đây là consdered phong cách xấu. Khai báo kiểu dữ liệu của bạn không nên có ràng buộc. Để lại các ràng buộc cho các hàm, giống như các gói chứa.

instance Eq (OutE vtype etype) where 

"Vấn đề thứ hai" thứ hai. Bạn chỉ có thể thêm deriving (Eq) sau khi khai báo dữ liệu của mình. Tôi đoán bạn biết điều đó và đang viết các ví dụ rõ ràng cho việc học tập của riêng bạn (tốt cho bạn) ...

instance Eq (OutE vtype etype) where 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

vấn đề thứ ba: bạn không thể so sánh giá trị cho công bằng nếu họ là của lớp Eq . Vì vậy, bạn muốn nói etype bị hạn chế bởi phương trình:

instance (Eq etype) => Eq (OutE vtype etype) where 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

Thứ tư, bạn không thực sự cần phải viết một ví dụ cho cả hai (==) và (/ =). Các giá trị mặc định sẽ hoạt động khi bạn xác định một trong các giá trị này.

+0

'deriving (Eq)' sẽ tạo các toán tử bình đẳng dựa trên ** tất cả các trường ghi ** (và do đó tạo ra một thể hiện 'Eq' phức tạp với' Eq vtype') trong khi cá thể rõ ràng được đưa ra trong câu hỏi chỉ so sánh dựa trên 'edgeValue '. – Dario

+0

Phải, tôi đã không nhận thấy anh ta đã làm điều đó cho đến khi viết xong. Cảm ơn bạn đã chỉ ra điều đó. –

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