2012-12-04 2 views
6

좋아, 나는 머리를 감싸기 위해 노력하고있어 기하학적 벡터 연산을위한 typeclass를 정의하려고한다. 나는 그것이 구성 요소 - 현명한 +,-,*,/;을 위해 일할 수 있었다. 그러나 나는 내적 제품으로 고투하고있다.하스켈 벡터 Typeclass : [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 

분명히 결과가 유형 Fractional a하지 Double의 때문에 (>.) 작동하지 않습니다 내 인스턴스 정의.

하지만 클래스의 선언에서이 동작을 얻는 방법을 모르겠습니다.

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

그러나 [a]이 형이 아닌 형태 변수이기 때문에이 유효하지 않습니다 : 내가 할 같은 을했던 것과

이다.

나는 이것을 조금 더 잘 설명 할 수 있었으면 좋겠지 만 솔직히 그렇게 할만큼 이해하지는 못한다. 잘하면이 코드는 내가 고심하고있는 것을 좀 더 분명하게 해줄 것이다.

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) 

그래서 GeomVector의 모든 인스턴스가 Monad 클래스와 같은 종류의 * -> *이있을 것이다 :

+1

스칼라 유형을 나타내는 다른 유형 변수, 즉'클래스 GeomVector a ... (>. :: a -> a -> s')가 필요하다고 생각합니다. – ErikR

+2

원하는 유형의 [연관 유형 동의어] (http://www.haskell.org/haskellwiki/GHC/Type_families#An_associated_type_synonym_example) – Lambdageek

+0

결과 유형이 (>.)이기 때문에 클래스 선언에 결함이 있습니다. 여러분은'''u''와'''v''의 내적을 생성하려고합니다. 여러분의 클래스 인스턴스가 아닌 리스트입니다. –

답변

5

여기에 일할 수있는 하나 개의 옵션입니다. 그리고 메소드의 유형은 불필요하게 Fractional 유형으로 제한되지 않습니다. 여기에 어딘가로 나누기 만하면됩니다.

클래스를 가능한 한 작게 만들거나 (>.을 클래스 외부의 다형성 함수로 만들기) 실제로 원하는 유형 클래스가 시작될 것인지 여부를 고려해야합니다. 그러나 모든 것은 당신이 디자인하고있는 것에 달려 있습니다. 나는 그것에 대해 당신보다 잘 알고 있다고 추정하고 싶지 않습니다!

+0

'> .'을 클래스 밖으로 이동하는 것은 불가능합니다. 왜냐하면 합계를 수행하기 위해'GeomVector'의 각 인스턴스의 내부 구조를 알아야하기 때문입니다. – huon

+1

그 문제는 toList를 추가하여 해결할 수 있습니다. –

+0

오른쪽, 죄송합니다. 그래서 한 가지 옵션은 class class (Foldable v) => GeomVector v'를 만드는 것입니다. – jberryman