Как указывает 陳 力, трудно ответить на вопрос, определяемый только именем функции и ее попыткой решения. Тем не менее, head
звучит так, как будто вы хотите взять первый элемент каждого подсписка, а col
звучит так, как будто вы рассматриваете этот список списков как матрицу с колонками, ортогональными подспискам.
Рекурсивное решение также может выглядеть следующим образом:
fun headcol [] = []
| headcol ((x::_)::xss) = x :: headcol xss
| headcol ([]::xss) = headcol xss
Вот как вы можете это сделать, используя встроенные комбинаторы списков высшего порядка:
fun headcol xss =
List.concat (List.map (fn xs => List.take (xs, 1)) xss)
Причина, по которой я не просто делаю:
fun headcol xss =
List.map hd xss
потому что hd
является частичной функцией, поэтому hd []
завершится сбоем во время выполнения.
С другой стороны, List.take ([], 1)
вернет []
.
И List.concat
объединят временный результат [[1],[2],[3]]
в [1,2,3]
.
Или, если столбец отсутствует, [[1],[],[3]]
в [1,3]
.
Контрольные примеры:
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]
Конечно, я не знаю, ожидаете ли вы такого поведения от headcol
в отношении нерегулярных матриц, у которых нет столбца заголовка. Это угловой случай, в который вы не пойдете. В функциональном программировании вы часто встраиваете обработку ошибок в возвращаемое значение, а не генерируете исключения.
Так, например, вы можете захотеть из headcol
вернуть 'a list option
, где SOME [1,4,7]
предполагает, что у каждой строки был столбец заголовка, а NONE
предполагает, что по крайней мере одна строка не смогла создать столбец.
Или вы можете использовать тип данных, отличный от 'a list list
, для представления вашей матрицы, которая не допускает строки с пропущенными столбцами, например, Array2 .