0

I am writing a function that will take a list of list and merge it into sorted pairs of list. For example [[1],[9],[8],[7],[4],[5],[6]] would return [[1,9],[7,8],[4,5],[6]]. This is my first attempt at SML. I keep getting this error: operator and operand don't agree [overload conflict].

    fun mergePass[] = []
    |   mergePass(x::[]) = x::[]
    |   mergePass(x::y::Z) = 
        if x<y
        then (x @ y)::mergePass(Z)
        else (y @ x)::mergePass(Z);

Edit: If mergePass is called on [[1,9],[7,8],[4,5],[6]] I will need it to return [[1,7,8,9],[4,5,6]].

This merge function takes two sorted lists

   fun merge([],y) = y
   |   merge(x,[]) = x
   |   merge(a::x,b::y) =
   if a < b then a::merge(x,b::y)
   else b::merge(a::x,y);
R_86
  • 35
  • 9
  • What line/expression causes the error? – Carcigenicate Mar 29 '17 at 00:12
  • This is the error that I get: stdIn:5.7-5.12 Error: operator and operand don't agree [overload conflict] operator domain: 'Z list * 'Z list operand: [< ty] * [< ty] in expression: x @ y stdIn:6.7-6.12 Error: operator and operand don't agree [overload conflict] operator domain: 'Z list * 'Z list operand: [< ty] * [< ty] in expression: y @ x – R_86 Mar 29 '17 at 01:33

1 Answers1

1

You seem reasonably close. A few hints/remarks:

1) Aesthetically, using nil in one line and [] in others seems odd. Either use all nil or use all []

2) Since the input are lists of lists, in x::y::z, the identifiers x and y would be lists of integers, rather than individual integers. Thus, x<y wouldn't make sense. You can't compare lists of integers using <.

3) Your problem description strongly suggests that the inner-lists are all 1-element lists. Thus you could use the pattern [x]::[y]::z to allow you to compare x and y. In this case, x@y could be replaced by [x,y]

4) If the inner lists are allowed to be of arbitrary size, then your code needs major revision and would probably require a full-fledged sort function to sort the result of concatenating pairs of inner lists. Also, in this case, the single list in the one inner list case should probably be sorted.

5) You have a typo: mergeP isn't mergePass.

On Edit:

If the sublists are each sorted (and the name of the overall function perhaps suggests this) then you need a function called e.g. merge which will take two sorted lists and combine them into a single sorted list. If this is for a class and you have already seen a merge function as an example (perhaps in a discussion of merge-sort) -- just use that. Otherwise you will have to write your own before you write this function. Once you have the merge function, skip the part of comparing x and y and instead have something as simple as:

| mergePass (xs::ys::zss) = (merge xs ys) :: mergePass zss

If the sublists are not merged, then you will need a full-fledged sort in which case you would use something like:

| mergePass (xs::ys::zss) = sort(xs @ ys) :: mergePass zss
John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • Making the changes you suggested did work but I have run into the problem where my list will not always be single integers. So if mergePass is used on [[1,9],[7,8],[4,5],[6]] I will need it to return [[1,7,8,9],[4,5,6]] – R_86 Mar 29 '17 at 02:10
  • I do have a merge function but the way it is written it needs two list that are already sorted. Will add the code above – R_86 Mar 29 '17 at 02:46