I want to make function named headcol
that works like:
headcol[[1,2],[3,4]] = [1,3];
So i made function like this:
fun headcol [] = []
| headcol [x::xs',y::ys'] = [x,y]
but when I call it, I get a match nonexhaustive.
I want to make function named headcol
that works like:
headcol[[1,2],[3,4]] = [1,3];
So i made function like this:
fun headcol [] = []
| headcol [x::xs',y::ys'] = [x,y]
but when I call it, I get a match nonexhaustive.
IIUC, headcol
will extract all heads of lists in the parameter, whose type is 'a-list-list
. What you mathc is only []
and [x::xs', y::ys']
, not anything else. So, if your argument has more than 2 sublists, execption will raise:
- headcol[[1,2],[3,4], [4, 5, 9]];
uncaught exception Match [nonexhaustive match failure]
raised at: a.sml:9.34
-
If you just want to deal with two-elems list, pair is a better choice. Otherwise, you should match more cases:
fun headcol list =
case list of
[] => []
| x::xs' =>
case x of
[] => headcol xs'
| h::t => h::(headcol xs')
output:
- headcol[[1,2],[3,4], [4, 5, 9]];
- val it = [1,3,4] : int list
As 陳 力 points out, it is hard to answer a question defined only by the name of a function and its attempted solution. Still, head
sounds like you want to take the first element of each sub-list, and col
sounds like you're treating this list of lists as a matrix with columns being orthogonal to to the sub-lists.
The recursive solution might also look like:
fun headcol [] = []
| headcol ((x::_)::xss) = x :: headcol xss
| headcol ([]::xss) = headcol xss
Here is how you might do it using built-in higher-order list combinators:
fun headcol xss =
List.concat (List.map (fn xs => List.take (xs, 1)) xss)
The reason why I'm not simply doing:
fun headcol xss =
List.map hd xss
is because hd
is a partial function, so hd []
will crash at run-time.
On the other hand, List.take ([], 1)
will return []
.
And List.concat
will combine the temporary result [[1],[2],[3]]
into [1,2,3]
.
Or, in case a column is missing, [[1],[],[3]]
into [1,3]
.
Test cases:
val test_headcol_0 = headcol [] = []
val test_headcol_1 = headcol [[1]] = [1]
val test_headcol_2 = headcol [[1,2],[3,4]] = [1,3]
val test_headcol_3 = headcol [[1,2,3],[4,5,6],[7,8,9]] = [1,4,7]
val test_headcol_4 = headcol [[1],[2,3],[4,5,6]] = [1,2,4]
val test_headcol_5 = headcol [[1],[],[2,3]] = [1,2]
Of course, I don't know if that's the behavior you expect from headcol
with regards to irregular matrices that don't have a head column. This is a corner case you don't go into. In functional programming, you often embed error handling into the return value rather than throw exceptions.
So for example, you could want from headcol
to return an 'a list option
where SOME [1,4,7]
suggests that each row did have a head column, and NONE
suggests that at least one row failed to produce a column.
Or you could use a data type other than 'a list list
to represent your matrix that does not allow rows with missing columns, e.g. an Array2.