2012-12-04 37 views
6

Được rồi, tôi đang cố gắng quấn đầu quanh máy chữ, và vì vậy tôi đang cố gắng xác định kiểu chữ cho hoạt động vectơ hình học. Tôi quản lý để có được nó làm việc cho thành phần khôn ngoan +,-,*,/; nhưng tôi đang đấu tranh với các sản phẩm dot.Haskell Vector Typeclass: Chức năng của [a] -> [a] -> a

class GeomVector a where 
    (>+) :: a -> a -> a 
    (>-) :: a -> a -> a 
    (>*) :: a -> a -> a 
    (>/) :: a -> a -> a 

    (>.) :: a -> a -> Double 

data Vector a = Vec [a] 
       deriving Show 

instance (Fractional a) => GeomVector (Vector a) where 
    (>+) (Vec u) (Vec v) = Vec $ zipWith (+) u v 
    (>-) (Vec u) (Vec v) = Vec $ zipWith (-) u v 
    (>*) (Vec u) (Vec v) = Vec $ zipWith (*) u v 
    (>/) (Vec u) (Vec v) = Vec $ zipWith (/) u v 

    (>.) (Vec u) (Vec v) = sum $ u >* v 

Rõ ràng định nghĩa ví dụ của tôi cho (>.) Sẽ không làm việc bởi vì kết quả là loại Fractional a, không Double.

Nhưng tôi không biết cách thực hiện hành vi này từ khai báo trong lớp học.

gì tôi muốn như cần làm là:

class GeomVector [a] where 
    (>.) :: [a] -> [a] -> a 

Nhưng điều này là không hợp lệ vì [a] là một loại và không phải là một loại biến.

Tôi ước tôi có thể giải thích điều này tốt hơn một chút, nhưng tôi thành thật không hiểu đủ để làm như vậy. Hy vọng rằng mã sẽ làm cho nó rõ ràng hơn một chút những gì tôi đang đấu tranh với.

+1

Tôi nghĩ bạn cần một biến kiểu khác để biểu thị loại vô hướng, tức là 'lớp GeomVector a ở đó ... (>.) :: a -> a -> s'. – ErikR

+2

Điều bạn muốn là [Từ đồng nghĩa loại được liên kết] (http://www.haskell.org/haskellwiki/GHC/Type_families#An_associated_type_synonym_example) – Lambdageek

+0

Tuyên bố lớp học của bạn không hoàn thiện không chỉ vì loại kết quả (>.). Bạn cần phải tạo ra một sản phẩm chấm của '' 'u''' và' '' v''' là các danh sách , không phải là trường hợp của lớp học của bạn. –

Trả lời

5

Dưới đây là một lựa chọn mà có thể làm việc:

class GeomVector v where 
    (>+) :: Num a=> v a -> v a -> v a 
    (>-) :: Num a=> v a -> v a -> v a 
    (>*) :: Num a=> v a -> v a -> v a 
    (>/) :: Fractional a=> v a -> v a -> v a 
    (>.) :: Num a=> v a -> v a -> a 

data Vector a = Vec { vecList :: [a] } 
       deriving Show 

instance GeomVector Vector where 
    (>+) (Vec u) (Vec v) = Vec $ zipWith (+) u v 
    (>-) (Vec u) (Vec v) = Vec $ zipWith (-) u v 
    (>*) (Vec u) (Vec v) = Vec $ zipWith (*) u v 
    (>/) (Vec u) (Vec v) = Vec $ zipWith (/) u v 

    (>.) u v = sum $ vecList (u >* v) 

Vì vậy, tất cả các trường lại GeomVector sẽ có một loại * -> * như lớp Monad. Và các loại phương pháp không nhất thiết bị giới hạn ở các loại Fractional chỉ vì bạn phân chia đâu đó trong đó.

Bạn cũng có thể xem xét làm cho lớp học của bạn càng nhỏ càng tốt (làm cho >. một chức năng đa hình bên ngoài lớp) và liệu những gì bạn thực sự muốn là một loại lớp để bắt đầu. Nhưng tất cả điều đó phụ thuộc vào những gì bạn đang thiết kế, và tôi không muốn cho rằng tôi biết rõ hơn bạn về điều đó!

+0

Có lẽ không thể di chuyển '> .' ra khỏi lớp, vì nó cần phải biết về cấu trúc bên trong của mỗi cá thể của' GeomVector' để làm tổng. – huon

+1

Vấn đề đó có thể được giải quyết bằng cách thêm một 'toList'. –

+0

đúng, xin lỗi. Vì vậy, một lựa chọn sẽ là làm cho lớp 'class (Foldable v) => GeomVector v' nếu điều đó có ý nghĩa. – jberryman

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