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)
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"