2011-12-16 31 views
8

Tuy mới để Haskell, tôi đã đánh một bức tường với những điều sau:Loại nghĩa lớp với các chức năng tùy thuộc vào một loại bổ sung

Tôi cố gắng để xác định một số các lớp học kiểu để khái quát một loạt các chức năng sử dụng phép khử Gauss để giải các hệ phương trình tuyến tính.

Cho một hệ thống tuyến tính

M x = k 

loại a trong những yếu tố m(i,j) \elem M có thể khác nhau từ các loại b của xk. Để có thể giải quyết hệ thống, a phải là một thể hiện của Numb nên có nhà khai thác nhân/Ngoài ra với b, giống như trong những điều sau đây:

class MixedRing b where 
    (.+.) :: b -> b -> b 
    (.*.) :: (Num a) => b -> a -> b 
    (./.) :: (Num a) => b -> a -> b 

Bây giờ, ngay cả trong việc thực hiện tầm thường nhất của các nhà khai thác, tôi sẽ nhận được Could not deduce a ~ Int. a is a rigid type variable lỗi (Hãy quên đi ./. đòi hỏi Fractional)

data Wrap = W { get :: Int } 
instance MixedRing Wrap where 
    (.+.) w1 w2 = W $ (get w1) + (get w2) 
    (.*.) w s = W $ ((get w) * s) 

tôi đã đọc nhiều hướng dẫn về các lớp học kiểu nhưng tôi có thể tìm thấy không có con trỏ đến những gì thực sự gặp khó khăn.

+5

Đã có gói định nghĩa lớp này: http://hackage.haskell.org/packages/archive/vector-space/0.8.0/doc/html/Data-VectorSpace.html Bạn có thể xem nhanh ở đó. –

+0

@SjoerdVisscher: Cảm ơn bạn! – bbtrb

Trả lời

10

Hãy để chúng tôi xem xét loại triển khai mà bạn sẽ phải cung cấp cho (.*.) để tạo Wrap một phiên bản MixedRing.Thay Wrap cho b trong các loại phương pháp này mang lại

(.*.) :: Num a => Wrap -> a -> Wrap 

Như Wrap là đẳng cấu với Int và để không phải suy nghĩ về gói và unwrapping với Wrapget, chúng ta hãy làm giảm mục tiêu của chúng tôi để tìm một thực hiện

(.*.) :: Num a => Int -> a -> Int 

(bạn thấy rằng điều này không làm cho các thách thức bất kỳ dễ dàng hơn hoặc khó khăn hơn, phải không?)

Bây giờ, hãy quan sát rằng việc thực hiện như vậy sẽ cần để có thể hoạt động trên tất cả các loại a xảy ra trong loại loại Num. Lưu ý: điều này không giống nhau (thực ra, ngược lại) khi nói rằng việc thực hiện của bạn có thể tự chọn những gì a để hoạt động); nhưng đó là những gì bạn có vẻ đề xuất trong câu hỏi của bạn: rằng việc triển khai của bạn phải được phép chọn Int làm lựa chọn cho a.

Bây giờ, khi bạn muốn thực hiện đặc biệt (.*.) này trong điều khoản của (*) cho các giá trị của loại Int, chúng ta cần một cái gì đó có dạng

n .*. s = n * f s 

với

f :: Num a => a -> Int 

Tôi không thể nghĩ ra một hàm chuyển đổi từ một số Num-kiểu a thành Int một cách có ý nghĩa. Do đó, tôi muốn nói rằng không có cách nào có ý nghĩa để thực hiện Int (và, do đó, Wrap) một phiên bản của MixedRing; đó là, không phải như vậy mà các trường hợp ứng xử như bạn có thể mong đợi nó để làm.

+0

Giải thích rất tốt. Trên thực tế có 2 lỗi: Thứ nhất, người ta không thể khởi tạo (từ định nghĩa lớp) trong định nghĩa cá thể và b) con đường. *. được thực hiện nguyên nhân b = một anyway và mâu thuẫn do đó loại. *. được đưa ra trong lớp. – Ingo

+0

Cảm ơn bạn đã giải thích tuyệt vời này. Cùng với các câu trả lời khác cũng như liên kết đến gói 'VectorSpace', điều này làm rõ vấn đề. – bbtrb

2

Triển khai của bạn không đủ đa hình.

Quy tắc là, nếu bạn viết a trong định nghĩa lớp, bạn không thể sử dụng loại cụ thể trong cá thể. Vì cá thể phải phù hợp với lớp học và lớp học hứa sẽ chấp nhận bất kỳ a nào là Num.

Để đặt nó một cách khác nhau: chính xác biến lớp là nó phải được khởi tạo với một loại cụ thể trong một định nghĩa cá thể.

Các bạn đã thử:

data Wrap a = W { get :: a } 

Lưu ý rằng một khi Wrap a là một ví dụ, bạn vẫn có thể sử dụng nó với chức năng mà chỉ chấp nhận Wrap Int.

+0

Có, tôi đã thử điều này - có và không có hạn chế 'dụ (Num a) => MixedRing (Wrap a) trong đó' - và nó đã không giúp đỡ. – bbtrb

+0

Nhưng điều này là do bạn thực hiện. *., Xem nhận xét 'dblhelix'. – Ingo

6

Làm thế nào về một cái gì đó như:

class (Num a) => MixedRing a b where 
    (.+.) :: b -> b -> b 
    (.*.) :: b -> a -> b 
    (./.) :: b -> a -> b 

Bạn sẽ cần phần mở rộng MultiParamTypeClasses.

Nhân tiện, dường như với tôi cấu trúc toán học mà bạn đang cố tạo mô hình thực sự là mô-đun, không phải là vòng. Với các biến loại được đưa ra ở trên, một biến cho biết b là một a -module.

+0

Không biết có nhiều loại lớp tham số, hoạt động này. Và bạn là đúng tất nhiên, mô-đun là thuật ngữ chính xác. Nhà vật lí, chứ không phải nhà toán học ở đây, xấp xỉ là đủ tốt;) – bbtrb

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