1
votes

Hello I am new to Sml/nj, and I am trying to modify an input to give it to a function. I'm stuck at modifying the input.

Specifically, I read the input and store it in a list. I want to make a function that given an even length list, it will make a new list, but with 2-element tuples.
For example, if my input is the list [2, 7, 4, 6, 5, 8] I want to create this list [(2, 7), (4, 6), (5, 8)]

I tried this but unfortunately it doesn't work:

fun maketuples [] = []
  | maketuples x::xs = (x, hd xs) @ makektuples (tl xs)
1

1 Answers

3
votes

There's a couple things here:

  • If you're pattern matching on a constructor as a function argument, you need to put parentheses around it for it to be parsed the way you'd like, i.e., x::xs -> (x::xs)

  • You have a typo in the second clause (makektuples; extra k)

  • You're using append (@) on a int * int and a (int * int) list. The domain of this function is in fact, 'a list * 'a list, i.e., both of its arguments must be lists of the same type.

We could revise this like so:

fun maketuples [] = []
  | maketuples (x::xs) = [(x, hd xs)] @ maketuples (tl xs)

But singleton append isn't really something you should do. Why? It's cleaner to just use cons:

fun maketuples [] = []
  | maketuples (x::xs) = (x, hd xs) :: maketuples (tl xs)

We can clean this up some more by removing the calls to hd and tl by just destructing further in the function arguments

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

and you could perhaps handle an error better (one possibility being with exceptions):

fun maketuples [] = []
  | maketuples (x::y::xs) = (x, y) :: maketuples xs
  | maketuples _ = raise Fail "Not an even length list"