Помогите мне объяснить функцию транспонирования F # Matrix
Существует функция Матрица транспонирования:
let rec transpose = function
| (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
[[1; 2; 3]; [4; 5; 6]; [7; 8; 9]] |> transpose |> printfn "%A"
Он отлично работает.
Что означает (_:: _):: _?
Я не понимаю весь код!
Кто может это объяснить?
Спасибо!
Я нахожу ответ:
(_:: _):: _ - это сопоставление шаблонов по значению типа списка списков ints
Если я пишу:
let rec transpose (M:int list list) =
match M with
| hd::tl -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
Он выдает исключение во время выполнения. Что-то не так с hd?
Да, он делает что-то вроде [[], []; []] при вызове List.tail, затем он выдает исключение при вызове List.head!
Проблема решена!
Спасибо всем!
Ответы
Ответ 1
Функция не особенно читается, что может быть причиной вашей путаницы. Конструкция (_::_)::_
- это сопоставление шаблонов по значению списка типов списков int, в котором говорится, что первый случай должен выполняться при получении непустого списка непустых списков.
То же самое можно написать так. Это более подробно, но должно быть ясно, что здесь происходит:
let rec transpose matrix =
match matrix with // matrix is a list<list<int>>
| row::rows -> // case when the list of rows is non-empty
match row with // rows is a list<int>
| col::cols -> // case when the row is non-empty
// Take first elements from all rows of the matrix
let first = List.map List.head matrix
// Take remaining elements from all rows of the matrix
// and then transpose the resulting matrix
let rest = transpose (List.map List.tail matrix)
first :: rest
| _ -> []
| _ -> []
Как вы можете видеть, нам действительно не нужны значения row
, rows
, col
и cols
. Поэтому исходная реализация заменяет их на _
(которая игнорирует значение и проверяет, что список может быть разложен соответствующим образом).
В рекурсивном случае мы деконструируем матрицу следующим образом:
[ [ x; y; y ]; [ y; y ]
[ x; y; y ]; => [ x; x; x] :: transpose [ y; y ]
[ x; y; y ] ] [ y; y ]
Я надеюсь, что картина сделает это более понятным для вас!
Ответ 2
Это также может помочь вам:
Понимание функции транспонирования матрицы в Haskell
Это очень похожая функция на аналогичном языке программирования (Haskell).
Ответ 3
(_::_)::_
соответствует шаблону. _
- просто неиспользуемая переменная. Это будет эквивалентно:
(a::b)::c as M -> List.map List.head M :: transpose (List.map List.tail M)
Ответ 4
Это отображает head
по спискам для извлечения первого столбца и использует это для формирования первой строки, предшествующей результату переноса остальных столбцов.
Ответ 5
Мне жаль, что вы столкнулись с устаревшей нитью, но ваш первоначальный ответ почти прав. Единственное, что неправильно, это условие завершения для пустого списка. Код должен выглядеть примерно так:
let rec transpose M =
match M with
| []::_ -> []
| _ -> List.map List.head M::transpose(List.map List.tail M)