porcupine
porcupine

Reputation: 23

Failing to use map on my own defined data structure

I defined my own rose tree and tried to sum its content. All the types match, but it fails to compile for an unknown reason.
That's my piece of code:

data Tree a = Tree {element :: a, branch :: [Tree a]} deriving (Show)
sumTree :: (Num a) => Tree a -> a
sumTree x = element(x) + sum.map (sumTree) branch(x)

I am getting these errors:

Prelude> ::l tree.hs
[1 of 1] Compiling Main             ( tree.hs, interpreted )

tree.hs:3:32: error:
    • Couldn't match expected type ‘Tree a -> t0 a’
                  with actual type ‘[b0]’
    • The function ‘map’ is applied to three arguments,
      but its type ‘(Tree b0 -> b0) -> [Tree b0] -> [b0]’ has only two
      In the first argument of ‘sum’, namely ‘(map (sumTree) branch (x))’
      In the second argument of ‘(+)’, namely
        ‘(sum (map (sumTree) branch (x)))’
    • Relevant bindings include
        x :: Tree a (bound at tree.hs:3:9)
        sumTree :: Tree a -> a (bound at tree.hs:3:1)
  |
3 | sumTree x = element(x) + (sum (map (sumTree) branch(x)))
  |                                ^^^^^^^^^^^^^^^^^^^^^^^

tree.hs:3:46: error:
    • Couldn't match expected type ‘[Tree b0]’
                  with actual type ‘Tree a0 -> [Tree a0]’
    • Probable cause: ‘branch’ is applied to too few arguments
      In the second argument of ‘map’, namely ‘branch’
      In the first argument of ‘sum’, namely ‘(map (sumTree) branch (x))’
      In the second argument of ‘(+)’, namely
        ‘(sum (map (sumTree) branch (x)))’
  |
3 | sumTree x = element(x) + (sum (map (sumTree) branch(x)))
  |                                              ^^^^^^

When clearly

Prelude> :t branch
branch :: Tree a -> [Tree a]

Upvotes: 2

Views: 60

Answers (2)

Will Ness
Will Ness

Reputation: 71065

Parentheses in Haskell serve for grouping of code elements only. Haskell function call syntax is not f(x), it is simply f x.

You wrote

sumTree x = element(x) + sum.map (sumTree) branch(x)

which is the same as

sumTree x = element x + sum . map sumTree branch x

but you meant

sumTree x = element x + sum . map sumTree (branch x)

The dot is still misplaced, you wanted it to be

sumTree x = element x + (sum $ map sumTree (branch x))

which is the same as

sumTree x = element x + sum (map sumTree (branch x))

Upvotes: 4

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476699

You here applied the map on the branch :: Tree -> Tree a function, instead of the result of branch x. This is due to the fact that te parenthesis are written in the wrong way.

You can implement your function as:

sumTree :: Num a => Tree a -> a
sumTree x = element x + sum (map sumTree (branch x))

Here we thus call map with sumTree and (branch x) as parameters.

Here branch x will thus generate the list of branches, we then call map sumTree on that list to generate the sum of each subtree, and then we sum these up with sum. We then add element x to the result.

Upvotes: 2

Related Questions