2017-10-24 5 views
2

다음 함수를 사용하여 주어진 목록의 모든 숫자를 현재 위치까지 합산해야합니다. 예 subtotal [1, 2, 3, 4] = [1, 3, 6, 10]를 들어, 1 = 1, 1 + = 3 2 + 2 + 3 = 6 1 1 + 2 + 3 + 4 여기 = 10예상 유형`[a] '과 실제 유형`a'를 일치시킬 수 없습니다.

내 코드 왜냐하면 :

subtotal :: Num a => [a] -> [a] 
subtotal [] = [] 
subtotal xs = [y | n <- [1..length xs], y <- sum(take n xs)] 

문제가 발생했습니다 :

cw.hs:3:46: error: 
    * Couldn't match expected type `[a]' with actual type `a' 
     `a' is a rigid type variable bound by 
     the type signature for: 
      subtotal :: forall a. Num a => [a] -> [a] 
     at cw.hs:1:1-31 
    * In the expression: sum (take n xs) 
     In a stmt of a list comprehension: y <- sum (take n xs) 
     In the expression: 
     [y | n <- [1 .. length xs], y <- sum (take n xs)] 
    * Relevant bindings include 
     xs :: [a] (bound at cw.hs:3:10) 
     subtotal :: [a] -> [a] (bound at cw.hs:2:1) 
    | 
3 | subtotal xs = [y | n <- [1..length xs], y <- sum(take n xs)] 
    |            ^^ 

어떻게 해결할 수 있습니까?

+0

'y <- [sum (take n xs)]'와 같이'sum (take n xs)'주위에 괄호를 넣으면 황금이됩니다. [this] (https://wiki.haskell.org/Keywords#.3C-), [this] (https://wiki.haskell.org/Keywords#.2C) 및 [this] (https : /wiki.haskell.org/Keywords#.7C). –

답변

7

sum(take n xs)이고 목록이이 아니므로 반복 할 수 없습니다.

subtotal :: Num a => [a] -> [a] 
subtotal xs = [sum (take n xs) | n <- [1..length xs]]

을하지만 당신은 여기 length을 사용 목록에 식의 결과를 추가하기 위해 당신은 지능형리스트의 머리에 표현을 넣어 . length은 목록이 무한 할 수 있기 때문에 약간 위험한 함수입니다. 그러면 함수가 루핑을 계속하고 요소를 반환하지 않을 것입니다. 당신은 모든 목록을 얻을 그러나 inits를 사용할 수 있습니다

import Data.List(inits) 

subtotal :: Num a => [a] -> [a] 
subtotal xs = [sum sub | sub <- tail (inits xs)]

을하지만이 매우 효과적으로 여전히되지 않습니다 : :

Prelude Data.List> inits [1,4,2,5] 
[[],[1],[1,4],[1,4,2],[1,4,2,5]] 

그래서 당신이 사용할 수있는 지금 우리는 모든 하위리스트의 합을 계산합니다. 그러나 여기서 문제는 모든 목록의 합계를 개별적으로 계산한다는 것입니다. i의 결과는 단순히 i-1 번째 결과와 i 번째 요소의 합계가 xs 인 결과 이상적입니다. 우리는 scanl1 :: (a -> a -> a) -> [a] -> [a]를 사용할 수 있습니다

subtotal :: Num a => [a] -> [a] 
subtotal xs = scanl1 (+) xs 

또는 더 간단하고 우아한 :

subtotal :: Num a => [a] -> [a] 
subtotal = scanl1 (+) 
4

을 지능형리스트에서 문 y <- ysys이 목록과 그 목록의 요소를 y 반복이 있음을 의미합니다. 그래서 y <- sum (take n xs)sum이 목록을 생성하고 그 목록을 반복한다는 것을 의미합니다. 그러나 sum은 목록이 아닌 하나의 번호 만 생성합니다. 그래서 당신은 오류가 발생합니다.

subtotal xs = [y | n <- [1..length xs], let y = sum(take n xs)] 

또는 단지 이해의 머리에 직접 표현을 넣어 :

subtotal xs = [sum (take n xs) | n <- [1..length xs]] 

PS : 첫 번째 케이스 (

당신은 간단한 식을 할당 할 let 대신 <-를 사용하려면 빈 목록에 대한) 중복됩니다. 그것은 두 번째 사건의 특별한 경우에 불과합니다.