2013-03-08 26 views
8

Tôi đang chơi xung quanh cố gắng hiểu các lớp học trong Haskell. Tôi đã viết một vài dòng mã ngớ ngẩn để thu thập nó. Tôi đã viết một lớp có tên là Slang có một chức năng. Khi tôi làm cho Integer trở thành một thể hiện của lớp, nó hoạt động tốt. Nhưng khi tôi tạo String một thể hiện của lớp của tôi, nó sẽ không biên dịch. Tôi đã được fidgeting với chương trình dựa trên những gì đầu ra lỗi cho tôi biết nhưng vô ích. Tôi có ý tưởng tại sao nó hoạt động ...Không thể tạo chuỗi một thể hiện của một lớp trong Haskell

Đây là đoạn mã tiếp theo là lỗi:

module Practice where 

class Slang s where 
    slangify :: s -> String 

instance Slang Integer where 
    slangify int = "yo" 

instance Slang String where -- When I take this segment out, it works fine 
    slangify str = "bro" 

LỖI:

Prelude> :load Practice 
[1 of 1] Compiling Practice   (Practice.hs, interpreted) 

Practice.hs:9:10: 
    Illegal instance declaration for `Slang String' 
     (All instance types must be of the form (T t1 ... tn) 
     where T is not a synonym. 
     Use -XTypeSynonymInstances if you want to disable this.) 
    In the instance declaration for `Slang String' 
Failed, modules loaded: none. 
Prelude> 
+0

Có bạn đã đúng !! Xin lỗi, tôi đã sửa nó – CodyBugstein

Trả lời

12

Vấn đề là chuỗi không phải là một kiểu cơ sở như Integer . Những gì bạn đang cố gắng làm thực sự là

instance Slang [Char] where 
    slangify str = "bro" 

Tuy nhiên, Haskell98 cấm kiểu này typeclass để giữ cho mọi thứ đơn giản và để làm cho nó khó khăn hơn cho người dân để viết các trường hợp chồng chéo như

instance Slang [a] where 
    -- Strings would also fit this definition. 
    slangify list = "some list" 

Dù sao, như thông báo lỗi cho thấy, bạn có thể vượt qua giới hạn này bằng cách bật tiện ích mở rộng FlexibleInstances.

+3

Cắm không biết xấu hổ cho một bài đăng blog cũ tôi đã viết khám phá cách đoạn dạo đầu được giới hạn trong giới hạn này [trong Hiển thị] (http://brandon.si/code/how-the-haskell-prelude-avoids-overlapping- loại-trong-show /). – jberryman

+1

@jberryman: Tuyệt. Đã không dừng lại để nghĩ về điều đó. – hugomg

+0

Làm cách nào để bạn bật FlexibleInstances? – CodyBugstein

5

Tôi đã thực hiện một số nghiên cứu trong tài liệu Haskell của tôi (còn gọi là Kinh Thánh hiện tại của tôi) và tìm thấy một ví dụ giải quyết vấn đề của tôi một cách hiệu quả. Về cơ bản, trong cách giải quyết này, bạn đặt Char là một thể hiện của lớp (trong ví dụ của sách được gọi là Visible) và sau đó bạn có thể đặt [chars] hay còn gọi là Chuỗi, là một thể hiện của lớp cũng CHỈ VỚI quy định rằng biến kiểu chars là một thể hiện của `Có thể nhìn thấy '. Đó là dễ hiểu nếu bạn nhìn vào mã bên dưới:

module Practice where 

class Visible a where 
    toString :: a -> String 
    size :: a -> Int 

instance Visible Char where 
    toString ch = [ch] 
    size _ = 1 

instance Visible a => Visible [a] where 
    toString = concat . map toString 
    size = foldr (+) 1 . map size 

My GHCi tải và chức năng gọi:

*Practice> :l Practice 
[1 of 1] Compiling Practice   (Practice.hs, interpreted) 
Ok, modules loaded: Practice. 
*Practice> size "I love Stack!" 
14 
*Practice> 

Eureka!

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