2016-10-15 3 views
1

나는 하스켈 (현재 패턴 매칭 학습)에서 초보자 해요 작동하지 않습니다 벡터를 정의 기능과 I는 벡터 정의에 대한 간단한 함수를 작성하려고 :하스켈

vector :: (Num a) => a -> a -> String 
vector 0 0 = "This vector has 0 magnitude." 
vector x y = "This vector has a magnitude of " ++ show(sqrt(x^2 + y^2)) ++ "." 

을하지만 오류의 무리를 얻을 수있는 나는 전혀 이해하지 못한다.

helloworld.hs:9:8: error: 
    • Could not deduce (Eq a) arising from the literal ‘0’ 
     from the context: Num a 
     bound by the type signature for: 
        vector :: Num a => a -> a -> String 
     at helloworld.hs:8:1-37 
     Possible fix: 
     add (Eq a) to the context of 
      the type signature for: 
      vector :: Num a => a -> a -> String 
    • In the pattern: 0 
     In an equation for ‘vector’: 
      vector 0 0 = "This vector has 0 magnitude." 

helloworld.hs:10:51: error: 
    • Could not deduce (Show a) arising from a use of ‘show’ 
     from the context: Num a 
     bound by the type signature for: 
        vector :: Num a => a -> a -> String 
     at helloworld.hs:8:1-37 
     Possible fix: 
     add (Show a) to the context of 
      the type signature for: 
      vector :: Num a => a -> a -> String 
    • In the first argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2))’ 
     In the second argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2)) ++ "."’ 
     In the expression: 
     "This vector has a magnitude of " 
     ++ show (sqrt (x^2 + y^2)) ++ "." 

helloworld.hs:10:56: error: 
    • Could not deduce (Floating a) arising from a use of ‘sqrt’ 
     from the context: Num a 
     bound by the type signature for: 
        vector :: Num a => a -> a -> String 
     at helloworld.hs:8:1-37 
     Possible fix: 
     add (Floating a) to the context of 
      the type signature for: 
      vector :: Num a => a -> a -> String 
    • In the first argument of ‘show’, namely ‘(sqrt (x^2 + y^2))’ 
     In the first argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2))’ 
     In the second argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2)) ++ "."’ 
Failed, modules loaded: none. 
Prelude> :load helloworld 
[1 of 1] Compiling Main    (helloworld.hs, interpreted) 

helloworld.hs:10:51: error: 
    • Could not deduce (Show a) arising from a use of ‘show’ 
     from the context: Integral a 
     bound by the type signature for: 
        vector :: Integral a => a -> a -> String 
     at helloworld.hs:8:1-42 
     Possible fix: 
     add (Show a) to the context of 
      the type signature for: 
      vector :: Integral a => a -> a -> String 
    • In the first argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2))’ 
     In the second argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2)) ++ "."’ 
     In the expression: 
     "This vector has a magnitude of " 
     ++ show (sqrt (x^2 + y^2)) ++ "." 

helloworld.hs:10:56: error: 
    • Could not deduce (Floating a) arising from a use of ‘sqrt’ 
     from the context: Integral a 
     bound by the type signature for: 
        vector :: Integral a => a -> a -> String 
     at helloworld.hs:8:1-42 
     Possible fix: 
     add (Floating a) to the context of 
      the type signature for: 
      vector :: Integral a => a -> a -> String 
    • In the first argument of ‘show’, namely ‘(sqrt (x^2 + y^2))’ 
     In the first argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2))’ 
     In the second argument of ‘(++)’, namely 
     ‘show (sqrt (x^2 + y^2)) ++ "."’ 
Failed, modules loaded: none. 

누군가가 어떻게 제대로이 기능을 작성하는 나를 설명 할 수, 적어도 무슨 일이 vector 0 0 잘못?

+0

힌트 :': t sqrt'와': t show'. – Jubobs

+0

가능한 오류 수정 방법을 시도 했습니까? –

답변

3

오류 메시지는 필요한 모든 것을 알려줍니다.

Could not deduce (Eq a) 

당신이 숫자 리터럴에 패턴 일치를 사용

, 그것은 제약 조건을 필요로 (Eq a, Num a) 하스켈 리터럴에 일치 할 내부적으로 ==을 사용하기 때문에. 당신이 show를 사용하면 모든 유형은 기본적으로 showable 때문에

Could not deduce (Show a) 

, 당신은 제약 (Show a)이 필요합니다. 모든 숫자 유형이이 작업을 지원하기 때문에이 같은 sqrt 같은 소수 연산을 사용

Could not deduce (Floating a) 

, 당신은 제약 (Floating a)이 필요합니다.

모두 함께 퍼팅 :

vector :: (Eq a, Num a, Show a, Floating a) => a -> a -> String 
vector 0 0 = "This vector has 0 magnitude." 
vector x y = "This vector has a magnitude of " ++ show(sqrt(x^2 + y^2)) ++ "." 

당신은 또한 다음 ghci 요청 유형 서명을 떠날 수 :

> let vector 0 0 = "This vector has 0 magnitude."; vector x y = "This vector has a magnitude of " ++ show(sqrt(x^2 + y^2)) ++ "." 
> :t vector 
vector :: (Eq a, Floating a, Show a) => a -> a -> [Char] 

을 그리고 여기 당신이 Num a 추가를 필요로하지 않는 것을 알 수 있습니다 FloatingNum의 서브 클래스이므로 Fractional에 의해 제한됩니다. 당신은뿐만 아니라 ghci에서 이러한 클래스에 대한 정보를 얻을 수 있습니다 :

> :info Floating 
class Fractional a => Floating a where 
    pi :: a 
    exp :: a -> a 
    log :: a -> a 
    sqrt :: a -> a 
    ... 
     -- Defined in ‘GHC.Float’ 
instance Floating Float -- Defined in ‘GHC.Float’ 
instance Floating Double -- Defined in ‘GHC.Float’ 

같은 매우 일반적인 코드를 작성, 당신은 일반적으로 사용하는 모든 제약 조건을 지정해야합니다. 그러나이 함수에 Double -> Double -> String과 같은보다 단순한 비 제네릭 유형을 제공 할 수도 있습니다.

4

첫 번째 유형 오류는 문자가 0 인 패턴 일치 때문입니다. 가능할 수 있도록 (Num a, Eq a)이 필요한 곳에 Num a이 필요했습니다.

두 번째 유형 오류는 a과 관련된 계산에서 show를 사용하려고했기 때문입니다. 이제 (Num a, Eq a, Show a)이 필요합니다.

셋째, Num에 없지만 Floating에있는 sqrt를 사용 했으므로 이제는 (Num a, Eq a, Show a, Floating a)입니다.

또는, 당신은 단지 전체 유형의 서명을 제거한 수 있고 ghci 유형에 대한 메시지 :

λ> :t vector 
vector :: (Show a, Floating a, Eq a) => a -> a -> [Char] 

하는 것으로 FloatingNum을 의미한다.

+0

첫 번째 것을 제외한 모든 것을 이해합니다. 저자는''Eq''없이 계승을위한 함수를 만들었고 작동했습니다 : ''factorial :: (Num a) => a -> String 계승 0 = 1 계승 n = n * 계승 (n - 1)' 어떻게 작동합니까? – Nikola

+0

@Nikola 나는 같은 누락 된'Eq'를 포함하여 여러 가지 방법으로 계승의 정의가 실패 할 것이라고 확신한다. – smarx

+0

@smarx 당신 말이 맞아요, 저자는''Num'' 대신에''Integral''을 사용했습니다 - 저의 실수입니다! – Nikola