2

I was trying to create a function in Standard ML which gets a list of string * int and returns a lexicography sorted list.

For example foo [("y",5),("x",10)] will return [("x,10),("y",5)] (only the first element of each tuple is important).

I wrote the following lines:

fun foo ([]:(string * int)) = []
  | foo [x] = [x]
  | foo ((x,y)::xs) = 
    let
      val (s,t) = hd(xs) (* gets next element string *)
      fun sort ... = ...
    in

    end

I don't know how to implement the sort function but I would like it to have the following code I wrote:

    case String.compare(x,s) of
      LESS => ...
    | EQUAL => ...
    | GREATER => ...

Also I need to use val (s,t) = hd(xs) in the sort function so it will be recursive but Im not sure. further more, I'm not allowed any additional libraries - only work with hidden let/local.

sshine
  • 15,635
  • 1
  • 41
  • 66

1 Answers1

0

(If you were allowed to use library functions,) ListMergeSort.sort in SML/NJ looks like:

val sort : ('a * 'a -> bool) -> 'a list -> 'a list

sort f l returns a list of the elements in l, sorted in non-decreasing order as specified by the ``greater than'' predicate f. Specifically, if f(x,y) evaluates to true, then x will appear after y in the resulting list.

Using this library function to write your foo:

fun foo pairs = ListMergeSort.sort (fn ((s : string,_), (t,_)) => s > t)

This might look a little different if you use another compiler than SML/NJ.


To address your sub-problems,

I don't know how to implement the sort function

(Since you're not allowed any library functions,) you could build a sorting function that takes String.compare as argument. Depending on the sorting algorithm, a rough sketch of the sorting function could look like:

fun sort cmp [] = []
  | sort cmp [x] = [x]
  | sort cmp xs = ... partially sort xs using `cmp`, combine results ...

and its signature would be ('a * 'a -> order) -> 'a list -> 'a list.

You're not asking how to make a sorting function (but merely saying that you don't know how to), and if you were, I would be inclined to say that this question is too broad when you don't specify what kind of algorithm you wish to implement, or where you got stuck in the process. See for example Rosetta Code's MergeSort, or the Q&A Standard sorting functions in SML?

I would like it to have the following code I wrote:

case String.compare (x,s) of ...

[...] I'm not allowed any additional libraries [...]

But String.compare is a library function, too! You could write your own String.compare. Either (a) explode the strings into char lists and use list recursion to determine their lexicographical order, or (b) count the length of the strings and use String.sub (s, i) to get the ith char of s for each string until the lexicographical order is determined. While (b) is more efficient (since it uses a small, constant amount of memory), (a) is a fine exercise in list recursion.

For (a) you could start with:

fun stringCompare (s, t) =
    let fun cmp (x::xs, y::ys) = if x < y then ... else ...
          | cmp (_::_, [])     = ...
          | cmp ([], _::_)     = ...
          | cmp ([], [])       = EQUAL
    in cmp (explode s, explode t) end

You can then compose them in the same way:

fun foo pairs = sort (fn ((s,_), (t,_)) => stringCompare (s, t)) pairs
Community
  • 1
  • 1
sshine
  • 15,635
  • 1
  • 41
  • 66