2012-12-04 9 views
6

Pekala, başlarımın etrafından dolaşmaya çalışıyorum ve bu yüzden geometrik vektör işlemleri için bir yazım hatası tanımlamaya çalışıyorum. Bileşen-bilge +,-,*,/; için çalışmayı başardım ama nokta ürünü ile uğraşıyorum.Haskell Vector Typeclass: İşlev [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 

Açıkçası sonuç tip Fractional a değil Double ait olduğu için (>.) Çalışmaz benim örnek tanım.

Ancak bu davranışı sınıftaki bildirimlerden nasıl alacağımı bilmiyorum.

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

Ama [a] bir tür değil, bir tür değişken olduğundan bu geçersiz: Yapmak gibi olur ne

olduğunu.

Keşke bunu biraz daha iyi açıklayabilseydim, ama dürüstçe bunu yapmaya yeteri kadar anlamıyorum. İnşallah kod, ben mücadele ile biraz daha belirgin hale getirecektir.

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) 

Yani GeomVector ait tüm örneklerini Monad sınıfı gibi bir tür * -> * sahip olacaktır:

+1

Sanırım skalerlerin türünü, yani 's GeomVector a s sınıfının türünü belirtmek için başka bir tür değişkene ihtiyacınız var. (>.) :: a -> a -> s'. – ErikR

+2

İstediğiniz nedir [İlişkilendirilmiş eşanlamlılar] (http://www.haskell.org/haskellwiki/GHC/Type_families#An_associated_type_synonym_example) – Lambdageek

+0

Sınıf bildiriminiz yalnızca (>.) Sonuç türü nedeniyle değil, yalnızca kusurludur. Sınıfınızın örneklerini değil, listeleri olan '' '' '' '' '' 'bir nokta ürünü üretmek için attemtp. –

cevap

5

Burada işe yarayabilir bir seçenek. Ve yöntemlerin türleri, orada bir yere böldüğünüz için gereksiz olarak Fractional türüyle sınırlı değildir.

Ayrıca, sınıfınızı olabildiğince küçük yapmayı (>. sınıfın dışında bir polimorfik işlev haline getirmeyi) ve gerçekten ne istediğinizi yazmaya başlamak için bir tür dersi oluşturmayı düşünebilirsiniz. Ama tüm bunlar sizin tasarladığınız şeye bağlıdır ve sizden daha iyi bildiğimi varsaymak istemiyorum!

+0

'>.' Sınıfının dışına taşınmak mümkün değildir, çünkü 'GeomVector' örneğinin iç yapısını bilmesi gerekir. – huon

+1

Bu sorun bir 'toList' eklenerek çözülebilir. –

+0

doğru, üzgünüm. Yani bir seçenek sınıf ('katlanabilir v) => GeomVector v' yapmak mantıklı ise. – jberryman