2012-06-25 28 views
6

Tôi viết một cấu trúc cây băm đơn giản trong chương trình sau hash_lookup.hs:Haskell: Khó khăn nhúng bối cảnh (Eq a) vào tờ khai dữ liệu

module Main where 

    data (Eq a) => HashTable a b = HashChildren (a, [HashTable a b]) | Hash (a, b) deriving (Show) 

    getKey :: HashTable a b -> a 

    getKey (HashChildren (k, hs)) = k 
    getKey (Hash (k, h)) = k 

    lookUp :: [a] -> HashTable a b -> Maybe (HashTable a b) 

    lookUp [] table = return table 
    lookUp _ (Hash _) = Nothing 
    lookUp (p:path) (HashChildren (_, ts)) = lookUp path (head (dropWhile (\x -> (getKey x) /= p) ts)) 

getKey được thiết kế để lấy chìa khóa gốc của Hashtable được và lookUp có một danh sách các chuỗi và có nghĩa là đi theo con đường đầu tiên nó tìm thấy cho đến khi nó đạt đến đường dẫn đầy đủ hoặc không thành công (tôi biết rằng đây không phải là hành vi tự nhiên đối với một cây nhưng đó là điều mà hướng dẫn của tôi muốn).

Tôi có hai câu hỏi: 1) Tại sao tôi lại nhận được một thông báo lỗi nói với tôi rằng a /= a (từ dòng cuối cùng) không được phép là có No instance for (Eq a) (thông báo lỗi trong thiết bị đầu cuối), mặc dù (Eq a) trong khai báo dữ liệu ?

2) Khác với các lỗi tôi nhận được và hành vi có vẻ kỳ lạ của các chức năng tra cứu, là này tốt hoặc ngữ Haskell?

Cảm ơn

+1

Tính năng ngữ cảnh dữ liệu sẽ bị xóa trong phiên bản tương lai của Haskell http://www.haskell.org/pipermail/haskell/2011-January/022497.html – sdcvvc

Trả lời

8

Một trong những "gotchas chung" trong Haskell là nếu bạn đặt chế lớp trên một tuyên bố data, mỗi chức năng sử dụng kiểu kết nối phải có những hạn chế lớp quá. Vì lý do này, khai báo data của bạn không phải là thành ngữ trong Haskell và bạn nên loại bỏ ràng buộc lớp của nó. Nó không giúp bạn có bất cứ điều gì để khai báo ràng buộc lớp trong khai báo data.

Về cơ bản, các loại chức năng phải lặp lại ràng buộc của lớp. Làm cách nào khác là người dùng của hàm biết rằng họ phải sử dụng một thể hiện của các lớp được đề cập? Lưu ý rằng bạn có thể có hàm f được xác định theo một hàm g được xác định theo điều khoản của h được xác định theo loại HashTable a b của bạn, chẳng hạn như f không đề cập đến loại HashTable của bạn, nhưng do loại phụ thuộc nó lấy một đối số thuộc loại a gián tiếp và cuối cùng được sử dụng làm thông số đầu tiên của loại HashTable của bạn. f 's loại phải có ràng buộc lớp, Haskell chính xác infers như vậy, và nó sẽ từ chối chú thích loại của bạn nếu họ thiếu nó.

+0

cảm ơn rất nhiều - điều này có ý nghĩa tuyệt vời! – GabrielG

+1

Lưu ý rằng chuẩn ngôn ngữ mới nhất đã loại bỏ hoàn toàn các ngữ cảnh kiểu dữ liệu. –

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