ML: совпадение не исчерпывающее - PullRequest
0 голосов
/ 01 ноября 2018

Я хочу сделать функцию с именем headcol, которая работает как:

headcol[[1,2],[3,4]] = [1,3]; 

Итак, я сделал такую ​​функцию:

fun headcol [] = [] 
  | headcol [x::xs',y::ys'] = [x,y]

но когда я звоню, я получаю неисчерпывающее совпадение.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Как указывает 陳 力, трудно ответить на вопрос, определяемый только именем функции и ее попыткой решения. Тем не менее, 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 .

0 голосов
/ 01 ноября 2018

IIUC, headcol извлечет все заголовки списков в параметре, тип которого 'a-list-list. То, что вы, mathc, это только [] и [x::xs', y::ys'], а не что-нибудь еще. Итак, если ваш аргумент имеет более 2 подсписков, execption будет вызывать:

- 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
...