Я хочу создать функцию с именем headcol
, которая работает так:
headcol[[1,2],[3,4]] = [1,3];
Итак, я сделал такую функцию:
fun headcol [] = []
| headcol [x::xs',y::ys'] = [x,y]
но когда я это называю, я получаю совпадение неисчерпывающим.
IIUC, headcol
извлечет все заголовки списков в параметре, тип которого - 'a-list-list
. То, что вы математикаете, - это только []
и [x::xs', y::ys']
, и ничего больше. Итак, если ваш аргумент имеет более двух подсписок, выполнение вызовет:
- headcol[[1,2],[3,4], [4, 5, 9]];
uncaught exception Match [nonexhaustive match failure]
raised at: a.sml:9.34
-
Если вы просто хотите иметь дело со списком из двух элементов, пара - лучший выбор. В противном случае вам следует сопоставить больше случаев:
fun headcol list =
case list of
[] => []
| x::xs' =>
case x of
[] => headcol xs'
| h::t => h::(headcol xs')
выход:
- headcol[[1,2],[3,4], [4, 5, 9]];
- val it = [1,3,4] : int list
Не могли бы вы переписать функцию, используя «карту»?
@ 이시온 Саймон дал исчерпывающую и идеальную демонстрацию map
. Если где-то вы чего-то не понимаете, не стесняйтесь указать на это.
Как указывает 陳 力, трудно ответить на вопрос, определяемый только именем функции и попыткой ее решения. Тем не менее, 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
, для представления вашей матрицы, которая не допускает строк с отсутствующими столбцами, например. Массив2.
nonexhaustive