帮我解释一下F#Matrix转置功能

kev*_*kev 14 f#

有一个矩阵转置功能:

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"
Run Code Online (Sandbox Code Playgroud)

它工作正常.
是什么(_ :: _):: _什么意思?
我不明白整个代码!
谁能解释一下?
谢谢!

我找到了答案:
(_ :: _):: _是匹配int类型列表的值的模式


如果我写:

let rec transpose (M:int list list) =
    match M with
    | hd::tl -> List.map List.head M :: transpose (List.map List.tail M)
    | _ -> []
Run Code Online (Sandbox Code Playgroud)

它抛出一个运行时异常.高清有什么问题吗?
是的,当调用List.tail时会产生类似[[]; []; []]的东西,然后在调用List.head时抛出异常!


问题解决了!
谢谢你们!

Tom*_*cek 27

该功能不是特别易读,这可能是您混淆的原因.构造(_::_)::_是一个模式匹配的类型列表的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
    | _ -> []
  | _ -> [] 
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我们并不真正需要的价值row,rows,colcols.这就是为什么原始实现取代了这些_(忽略了值,只检查列表是否可以按要求的方式分解).

在递归的情况下,我们解析矩阵,如下所示:

[ [ x; y; y ];                               [ y; y ] 
  [ x; y; y ];   =>  [ x; x; x] :: transpose [ y; y ]
  [ x; y; y ] ]                              [ y; y ] 
Run Code Online (Sandbox Code Playgroud)

我希望图片让你更清楚!


Tur*_*tle 5

这也可能对您有所帮助:

理解Haskell中的Matrix转置函数

它在类似的编程语言(Haskell)中是一个非常相似的函数.