1

I am fairly new to functional programming and I do not understand my error here. I am trying to make a function that takes an integer list and returns both the sum of the even elements and the sum of the odd elements. The error I am getting is in line 1, and it states: "Error: right-hand-side of clause doesn't agree with function result type [overload conflict] ...". I don't understand the error, and I would appreciate any help in understanding my error.

fun add(nil) = 0
|   add([x]) = x
|   add(x :: xs) =
        let
            val evenList = xs;
            val oddList = x :: xs
        in
            (hd evenList + add(tl(tl(evenList))), hd oddList + add(tl(tl(oddList))))
        end;
Asgore
  • 21
  • 5

1 Answers1

2

The reason for the type error is that the function should return a pair, but your base cases don't.

I suspect you got to that code by thinking about skipping every other element, dividing the list by skipping.

There's a different way to approach this.

Consider the list [a,b,c,d].

Counting from 1, the elements are numbered

1 2 3 4
a b c d

Now consider the positions in the tail of the list.
They are

1 2 3
b c d

That is, odd positions in the tail are even positions in the entire list, and even positions in the tail are odd in the entire list.

This means that if we recursively compute "odds and evens" in the tail, we will get the sums from the tail, where its "odds" is our "evens", and if we add our head to the tail's "evens", we will get the "odds" we want.

All we need now is a good base case – and the sums of an empty list must be (0, 0).

Something like this:

fun add [] = (0,0)
  | add (x::xs) = case add xs of
                      (odds, evens) => (x + evens, odds)

or, you can deconstruct the recursive result with a let-binding instead of case:

fun add [] = (0,0)
  | add (x::xs) = let val (odds, evens) = add xs
                   in
                       (x + evens, odds)
                   end
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • Thank you! I think I understand your approach, but I'm not familiar with the case expression. Is there a way to implement this approach using an if then else expression? – Asgore Oct 04 '18 at 20:02
  • @Asgore None that I can think of – there isn't anything that's conditional about this problem. The `case` is used for pattern matching, and since there is only one case there is only one clause. (`if C then T else E` is the same as `case C of true => T | false => E`.) – molbdnilo Oct 04 '18 at 22:37