2015-01-22 3 views
0

는 다음의 prodV의 마지막 패턴이 작동하지 않는 이유에 손실에서 약간 내가 해요 :반환 형식은

{-# LANGUAGE GADTs #-} 

data V a where 
    V0 :: Float -> V Float 
    Vn :: [Float] -> V [Float] 

prodV :: (Num a) => V a -> V a -> a 
prodV (V0 x) (V0 y) = x * y 
-- prodV (Vn x) (Vn y) = zipWith (*) x y -- this one works 
prodV (Vn xs) (Vn ys) = [ sum $ zipWith (*) xs ys ] 
prodV (V0 n) (Vn ys) = map (* n) ys 

GHCi 7.8.3 불평 :

Couldn't match type ‘Float’ with ‘[Float]’ 
Inaccessible code in 
    a pattern with constructor 
    Vn :: [Float] -> V [Float], 
    in an equation for ‘prodV’ 
In the pattern: Vn ys` 

포인터가 있습니까? 미리 감사드립니다.

+0

당신의 함수'prodV'가 모든'Num' 타입에서 작동 할 것으로 기대하지만,'V0'와'Vn' 생성자는 특별히'Float'을 포함합니다. 두 번째로, 'V a'의 'a'는 'Num'이어야하지만 'Num a => [a]'는 'Num'의 인스턴스가 아닙니다. 이 문제를 잘못된 방식으로 접근하고있는 것처럼 보입니다. – bheklilr

+2

"unV :: V a -> a'와 같은 함수를 작성할 수 있습니다. 단순히 생성자를 unwrap하지만 함수의 전제가 정확하지는 않습니다. 어쩌면 당신은'Vn :: [Float] -> V Float'을 고려해야 할 것이지만'Float'의리스트를 하나의'Float'로 변환하지 않으면'unV :: V a -> a'를 불가능하게 만들 것입니다 먼저 패션. – bheklilr

+0

Num 제약 조건을 제거하더라도 오류가 남아 있습니다. 나는 왜 V0와 Vn 생성자가 '혼합'될 수 없는지 잘 모르겠다. – ocramz

답변

2

서명 두 인수가 동일한 유형의 매개 변수를 가지고 있지만, 당신은 V0Vn에 일치하는 경우 인수가 유형 V FloatV [Float]하는 형식 매개 변수가 일치하지 않습니다을해야

prodV :: (Num a) => V a -> V a -> a 

의무 .

난 당신이 의미이 원하는 것을 확실히 모르겠지만 난 당신이

data V n where 
    V0 :: n -> V n 
    Vn :: [n] -> V n 

및 중

prodV :: (Num a) => V a -> V a -> V a 
prodV (V0 x) (V0 y) = V0 $ x * y 
prodV (Vn xs) (Vn ys) = Vn $ zipWith (*) xs ys 
prodV (V0 n) (Vn ys) = Vn $ map (* n) ys 
같은 함수 같은 것을 같이 GADT을 정의 할 같은데요

또는 가능

prodV' :: (Num a) => V a -> V a -> a 
prodV' (V0 x) (V0 y) = x * y 
prodV' (Vn xs) (Vn ys) = sum $ zipWith (*) xs ys 
prodV' (V0 n) (Vn ys) = sum $ map (* n) ys 

당신이 기능을 원하는 것을 설명 할 수,311 실제로 할? 원래 코드의 유형은 실제로 그대로 나에게 의미가 없습니다.

2

글쎄, GHC는 문제가 무엇인지 정확하게 알려줍니다. 귀하의 정의에서 V0 something은 항상 V Float 유형이며 something 유형은 Float이어야합니다. 그러나 여기에는 해당되지 않습니다. Vn anything은 항상 V [Float] 유형입니다. 그러나 prodV의 유형 서명은 두 유형 모두 동일한 유형 인 V a을 지정합니다. 따라서이 경우 a은 동시에 Float[Float]이어야하며 불가능합니다.

0

대수적인 속기를 모방하기 위해 함수를 오버로드하는 방법을 이해하려고 시도했지만, 이것이 올바른 길은 아닌 것 같습니다. 하스켈의 관용적 인 방법으로 어떻게 할 수 있습니까? 예 :

adaptScalar f1 f2 f3 x y 
    | dim x == 1 = f1 ([email protected]>0) y 
    | dim y == 1 = f3 x ([email protected]>0) 
    | otherwise = f2 x y 

instance Num (Vector Float) where 
    (+) = adaptScalar addConstant add (flip addConstant) 
    negate = scale (-1) 
    (*) = adaptScalar scale mul (flip scale) 
    signum = vectorMapF Sign 
    abs = vectorMapF Abs 
    fromInteger = fromList . return . fromInteger 

운영자의 오른쪽 구현 픽업 (예컨대 + 또는 *) 피연산자의 치수에있어서 Numeric.Matrix에서.

+0

자신 만의 질문에 대한 답변을 올리는 것은 좋은 방법이 아닙니다. 새 질문을하거나 원래 질문을 편집하십시오. – user2407038

관련 문제