Help me to explain the F# Matrix transpose function

前端 未结 5 761
后悔当初
后悔当初 2020-12-01 14:54

There is a Matrix transpose function:

let rec transpose = function
    | (_::_)::_ as M -> List.map List.head M :: transpose (List.map Li         


        
相关标签:
5条回答
  • 2020-12-01 15:13

    (_::_)::_ is pattern matching. _ is simply an unused variable. This would be equivalent:

    (a::b)::c as M -> List.map List.head M :: transpose (List.map List.tail M)
    
    0 讨论(0)
  • 2020-12-01 15:18

    The function is not particularly readably written, which may be the reason for your confusion. The construct (_::_)::_ is a pattern matching on value of type list of lists of ints that says that the first case should be run when you get a non-empty list of non-empty lists.

    The same thing can be written like this. This is more verbose, but it should be clear what is going on here:

    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
        | _ -> []
      | _ -> [] 
    

    As you can see, we don't really need the values row, rows, col and cols. That's why the original implementation replaces these with _ (which ignores the value and only checkes that the list can be decomposed in the required way).

    In the recursive case, we deconstruct the matrix like this:

    [ [ x; y; y ];                               [ y; y ] 
      [ x; y; y ];   =>  [ x; x; x] :: transpose [ y; y ]
      [ x; y; y ] ]                              [ y; y ] 
    

    I hope that the picture makes it more clear for you!

    0 讨论(0)
  • 2020-12-01 15:24

    This maps head over the lists to extract the first column and uses that to form the first row prepended to the result of transposing the remaining columns.

    0 讨论(0)
  • 2020-12-01 15:25

    I'm sorry for bumping an outdated thread, but your original answer is almost right. The only thing that's wrong is the termination condition for an empty list. The code should look something like this:

    let rec transpose M = 
        match M with 
        | []::_ -> []
        | _ -> List.map List.head M::transpose(List.map List.tail M)
    
    0 讨论(0)
  • 2020-12-01 15:26

    This may also help you:

    Understanding a Matrix transposition Function in Haskell

    It is a very similar function in a similar programming language (Haskell).

    0 讨论(0)
提交回复
热议问题