2016-08-24 5 views
0

하스켈을 배우는 동안 주어진 숫자의 모든 제수 약수를 반환하는 함수를 사용해야합니다. 그래서 두 개의 중첩 된 where 절을 사용하여 만들었지 만 작동하지 않습니다. exs2.hs:49:24: Parse error in pattern: negRef/2Haskell에서 중첩 된`where` 절 사용

divisors' :: (Integral a) => a -> [a] 
divisors' x = divs x (x/2) [x] 
    where 
    divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list) 
    divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list 
     where 
     negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList) 
     negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList 

후 잘못된 점은 무엇입니까 :

오류을 반환? 그것은 들여 쓰기가 잘 된 것 같습니다.

+4

'negRef/2'는 유효한 패턴이 아닙니다. – MathematicalOrchid

+3

내부 where 절이 div 정의에서 두 번째 행의 범위에만 있습니다. divs의 첫 번째 행에서 negDiv를 호출하면 내부 where 절이 범위에 없습니다. 그것과 패턴 것. – pigworker

+0

그러면 어떻게 그 구분 패턴을 올바르게 쓸 수 있습니까? @MathematicalOrchid – fant0me

답변

2

두 번째 where - 절에는 divs 범위의 이름이 사용되지 않습니다. 당신은 하나의 절과 같이 사용할 수 있습니다 : 당신이 정말로 중첩 된 조항과의 기능을 표현하고 싶다면, 당신은 let ... in을 사용할 수 있습니다

divisors' :: (Integral a) => a -> [a] 
divisors' x = divs x (x/2) [x] 
    where 
    divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list) 
    divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list 
    negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList) 
    negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList 

.

그러나이 경우 유용하지 않으므로 where 절 (대부분보다 선호되는데, 대부분의 경우 덜 관용적 인 것으로 간주 됨)을 사용하는 것이 좋습니다.

작동하지 않는 이유는 negDiv을 사용하는 첫 번째가 아니라 divs의 두 번째 방정식에 절이 첨부되어 있기 때문입니다.

추 신 : MathematicalOrchid said으로, negRef/2은 올바른 패턴이 아닙니다. 오류가 발생한 곳입니다.

+0

때로는'어디로'가'보내는'보다 바람직하며 때로는 다른 방향으로가는 경우가 있습니다. 나는 하나가 다른 것보다 관용적이라고 생각하지 않는다. 예를 들어 http://stackoverflow.com/questions/4362328/haskell-where-vs-let을 참조하십시오. –

2

또 다른 문제는 / 연산자가 정수에서 작동하지 않는다는 것입니다. 하스켈에서 /은 필드의 나누기 연산자이므로 Rational 또는 Double과 같은 Fractional 유형이 필요합니다.

의 경우 division의 경우 div or quot을 사용해야합니다.

+0

이전에'div'를 사용 했는데도 같은 오류가 나에게 돌아 왔습니다. – fant0me

1

당신은 몇 가지 문제가 있습니다

  1. 할 수 있습니다 리터럴 및 데이터 생성자, / 좋아하지 임의의 기능에만 패턴 일치.
  2. /Fractional a 값에 대해서만 정의되며 Integral이 아닙니다. 대신 div을 사용하십시오.
  3. negDiv의 정의에서 재귀 호출에서 인수가 누락되었습니다. 그러나 논쟁이 무엇인지 분명하지 않습니다.

주로 수정 된 버전 : 훨씬 더 간단하게

divisors' x = ds ++ (map negate ds)    -- positive and negative ds 
       where ds = filter (divs x) [1..x] -- d such that d divides x 
        x `divs` y = x `mod` y == 0 -- Does y divide x? 

또는

divisors' x = [d | d <- [(-x)..x], d /= 0, x `mod` d == 0] 

언제든지 함께 할 그런데

divisors' :: (Integral a) => a -> [a] 
divisors' x = divs x (x `div` 2) [x] 
    where 
    divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list) 
    divs ref num list | ref `mod` num == 0 = divs ref (num-1) (num:list) 
         | otherwise   = divs ref (num-1) list 
    -- Three arguments, but only two given to each recursive call 
    negDiv x y negList | x == negRef `div` 2 = x:y:negList 
         | x `mod` y == 0  = negDiv (y-1) (y:negList) 
         | otherwise   = negDiv (y-1) negList 

는,이된다 목록을 반복하는 재귀 함수를 작성하는 경우 올바른 고차 함수 또는 목록 이해가 간과 될 수 있습니다.