2014-01-09 5 views
0

큰 숫자를 정밀도로 계산할 수 있도록 새로운 유형을 만들고 있습니다. 기본적으로는 Double과 Integer를 사용하여 숫자를 Double * 10^Integer으로 나타냅니다. 이제는 프로그램을 만들기 시작했고 새로운 번호의 인스턴스를 만들려고 할 때까지 "ok"가되어 간단 번호 +을 사용하여 새 번호를 추가 할 수있었습니다. 이렇게하면 기존 프로그램에서 더 쉽게 사용할 수 있습니다. 하지만 난 그냥 내 코드에서 "추론 할 수 없다"라인을 따라 오류가 발생했습니다 (아래 예제를 게시 할 예정입니다). 나는 약간의 오류를 이해하지만, 나는 문제를 해결할 수있는 것처럼 보일 수있다. 코드를 컴파일하려면 4 행과 5 행을 주석 처리하십시오.연산자 오버로딩 :: HaskellNewbie

저는 몇 시간 동안이 작업을하고 있으며 "죽이기"입니다. 어떤 도움이 많이 감사합니다

sci.hs:5:40: 
    Could not deduce (a ~ Double) 
    from the context (Floating a, Integral b) 
    bound by the instance declaration at sci.hs:4:10-49 
    `a' is a rigid type variable bound by 
     the instance declaration at sci.hs:4:20 
    In the first argument of `(*)', namely `a' 
    In the expression: a * c 
    In the first argument of `Sci', namely `(a * c, b * d)' 

sci.hs:5:44: 
    Could not deduce (b ~ Integer) 
    from the context (Floating a, Integral b) 
    bound by the instance declaration at sci.hs:4:10-49 
    `b' is a rigid type variable bound by 
     the instance declaration at sci.hs:4:31 
    In the first argument of `(*)', namely `b' 
    In the expression: b * d 
    In the first argument of `Sci', namely `(a * c, b * d)' 

: 여기

newtype Sci f p = Sci (f ,p) deriving (Eq,Show) 


instance (Floating a,Integral b) => Num (Sci a b) where 
    Sci (a,b) * Sci (c,d) = fixSci(Sci(a*c,b*d)) 


mulSci :: Sci Double Integer -> Sci Double Integer -> Sci Double Integer 
mulSci (Sci(a,b)) (Sci(c,d)) = fixSci (Sci(a*c,b*d)) 


mkSci :: Double -> Sci Double Integer 
mkSci 0 = Sci(0, 0) 
mkSci n = let lg = (floor ((log10 . abs) n)) in Sci((n/(10**(fromIntegral lg))), if lg > 0 then lg else 0) 

fixSci :: Sci Double Integer -> Sci Double Integer 
fixSci (Sci(a,b)) = let n = mkSci a in (\(Sci(c,d)) -> Sci(c,b+d)) n 

fromSci (Sci(a,b)) = a*10**(fromIntegral b) 

showSci (Sci(a,b)) = (show a)++"e"++(show b) 

lx :: Double 
lx = log 10 

log10 :: Double -> Double 
log10 y = log y/lx 


-- ~ main = putStrLn $ showSci $ fixSci $ Sci(95,0) 
main = putStrLn $ showSci $ mkSci 95 

는 예를 들어 오류입니다!

+1

"하지만 난 그냥 ge 내 코드에서 오류가 발생했습니다. " 당신은 오류를 읽으려고 노력 했습니까? 그리고 그 문제를 핵심으로 줄였습니까? 두 오류 모두 5 행을 참조하십시오. –

+0

오류가 게시되면 도움이됩니다. 'Num' typeclass에 대한 최소한의 완전한 정의를 구현하는 것을 무시한 즉각적인 문제를 볼 수 있습니다. 당신은 또한'+','-'또는'negate','abs' 및'signum'을 필요로합니다. (모든 것이다고 생각하지만, 문서를 확인하십시오) – bheklilr

+0

[과학적] (http : // hackage. haskell.org/package/scientific-0.1.0.0) 패키지가 대신 유용할까요? –

답변

4

틀림없이 GHC 오류 메시지를 읽고 이해하는 것은 쉽지 않습니다. 그러므로 귀하의 질문은 유효합니다.

분명히 메시지는 사용자의 * 연산자에 대한 정의를 나타냅니다. sci.hs:5:40에 언급 된 줄 번호와 Num 인스턴스에 정의한 유일한 숫자는 (*)입니다.

*의 일반적인 유형을 기억, 그것은 의미

(*) :: Num n => n -> n -> n 

입니다 : 당신이 *에 해당 유형의이 개 값을 줄 경우 민 인스턴스가있는 모든 종류의 N를 들어, 다른 값을 다시 얻을 것이다 같은 유형의 또는 더 간단하다 : (*) 요소가 동일한 유형이고 결과가 요인과 동일한 유형 인 한 모든 숫자 유형에 사용할 수 있습니다.

* 구현시 반드시이 계약을 이행해야합니다.

(*) :: (Floating a, Integral b) => Sci a b -> Sci a b -> Sci a b 

그래서 당신은 당신의 곱셈은 어떤 유형 A와 B에 대한 유형 Sci a b을 위해 일만큼 A는 부동 유형이 같이 것이라고 주장하고 : 당신의 Sci 유형 자체가 다형성이기 때문에, 당신의 화신은 유형이 b는 Intergal 유형입니다. 즉, Sci Double Integer은 물론 Sci Float Int에 대해서도 작동해야합니다.

이제 오류가 무엇인지 알아야합니다. 구현 내용이 그 약속에 부합하지 않습니다. 사실 보조 기능 fixSciSci Double Integer에서만 작동 할 수 있기 때문에 Sci Double Integer에서만 작동합니다.

오류 메시지는 더 전문적인 형식으로 알려줍니다. 그것은

  1. 충돌 aDouble ("당신은 나에게 아무것도주지 약속하지만 내가 가진 모든 형편을 두 번했다!")
  2. 범위 내에서 실제로 제약 ("당신은 말했다 a이를 유형이었다 나열 Floating의 인스턴스)와 그것이 도입 된 곳.
  3. 컴파일러를 주도 식 (들)이 초보자 어쨌든 오류 메시지를 읽을 결코 : 흥미로운 부분 이전에 알려진대로 Double

불행하게도, 컴파일러, 간결 (짧은 중지 추론합니다. 정말 귀하의 질문에 관련되지

in the expression fixSci (Sci (a*c) (b*d)), 
and since fixSci takes an argument of type Sci Double Integer 
I concluded that Sci (a*c) (b*d) must be Sci Double Integer 
and hence (a*c) must be Double. 
+0

응답 덕분에 아주 좋았습니다. 언젠가는 다른 응답이 다소 위협적이었습니다. – Freakasuar

0

같은 것을 포함으나, 코드에 :

는 정말 mulSci (Sci(a,b)) (Sci(c,d)) = fixSci (Sci(a*c,b*d))을해야 하는가? b*d 대신 b+d일까요?

newtype Sci = Sci Double Integer을 설정하지 않으시겠습니까? 그럼 당신은

instance Num Sci where 
    (Sci m1 e1) * (Sci m2 e2) = fixSci (Sci (m1*m2) (e1+e2)) 
    (Sci m1 e1) + (Sci m2 e2) = <some rather complicated expression> 
+0

여기에'data'가 필요하거나 튜플을 떠납니다. – Ingo

+0

아 ... 네 말이 맞아요. 'newtype'은 코드에서와 같이 * 하나의 타입을 감싸기 만 할 수 있습니다 (복합 타입 일지라도). – md2perpe

+0

감사합니다. 이것은 내 눈이 어떻게 봐야했는지 보여주는 좋은 예입니다. 내 솔루션을 기반으로합니다. 그래, 내 코드에서 몇 가지 실수 중 하나입니다. 나중에 다른 사람들이 나중에 참조하도록 수정합니다. – Freakasuar

0

하지 원래 질문이 있습니다,하지만 당신의 showSci 기능은 나를 귀찮게 :

이 쇼는 자신의 쇼 기능을 쓰기 도출하지 마십시오 : 다음 main

instance Show Sci where 
    show (Sci (a,b)) = (show a) ++ "e" ++ (show b) 

가된다 :

main = print $ mkSci 95 
+0

내가 Sci 타입의 원시 뷰를 원했기 때문에 나는 당신이 위에서 말한 것을하는 법을 알지 못하기 때문에 쇼를 도출했다. 나는 플로트가 인쇄되는 것처럼 보이는 쇼 기능을 만들 계획이다. 팁 고마워 – Freakasuar