Loco Adol
Loco Adol

Reputation: 7

SML - Error: operator and operand do not agree [overload - bad instantiation]

I'm very new to SML and I need help with this problem,

What I'm trying to do is, I have a list of tuples of int * int and the output is a list where the elements of the tuples are added up, like this:

[(1,2),(3,4)...] = [3,7,....]

This is the code I did for this, but I have an error that I don't know how to solve

fun sumpares [] = []
  | sumpares [(x,y)] = [x+y]
  | sumpares ((x,y)::xs) = [x+y]::sumpares(xs)

This is the error:

stdIn:68.28-68.47 Error: operator and operand do not agree [overload - bad instantiation]
  operator domain: 'Z[OL(+,+)] list * 'Z[OL(+,+)] list list
  operand:         'Z[OL(+,+)] list * 'Z[OL(+,+)] list
  in expression:
    (x + y :: nil) :: sumpares xs

How can I fix it? Also, is there a way to do this if you have lists instead of tuples

Upvotes: 0

Views: 537

Answers (1)

Chris
Chris

Reputation: 36536

Consider your sumpares function. If we give it an empty list, it returns an empty list. That's easy.

In the next case, we feed it an (int * int) list and we get an int list in return. So far the type of sumpares is (int * int) list -> int list. But now consider the next case.

((x,y)::xs) does match an (int * int) list but then you return: [x+y]::sumpares(xs). An int list cannot be added to the front of an int list using ::. This would only work if sumpares(xs) returned an int list list.

There are a few ways to fix this.

First, there is no need for the second case with a single tuple at all. Let's get rid of that.

fun sumpares [] = []
  | sumpares ((x,y)::xs) = [x+y]::sumpares(xs)

This actually will compile because [] is an int list list, but an int list list is not what you're looking for. To get the desired result...

We could use the @ operator to concatenate the two lists.

fun sumpares [] = []
  | sumpares ((x,y)::xs) = [x+y] @ sumpares(xs)

But this is much less efficient than just constructing a list by tacking x+y onto the front of the list created by the recursive call.

fun sumpares [] = []
  | sumpares ((x,y)::xs) = (x+y) :: sumpares(xs)

It may also be useful to realize that what you're doing is reimplementing a very specific use of map.

val sumpares = map op+

You can definitely see this by looping at a simple implementation of map.

fun map _ [] = []
  | map f (x::xs) = f x :: map f xs

Upvotes: 2

Related Questions