Understanding this matrix transposition function in Haskell

前端 未结 3 2051
伪装坚强ぢ
伪装坚强ぢ 2021-02-12 06:43

This matrix transposition function works, but I\'m trying to understand its step by step execurtion and I don\'t get it.

    transpose:: [[a]]->[[a]]
    tran         


        
相关标签:
3条回答
  • 2021-02-12 07:24

    Let's look at what the function does for your example input:

    transpose [[1,2,3],[4,5,6],[7,8,9]]
    <=>
    (map head [[1,2,3],[4,5,6],[7,8,9]]) : (transpose (map tail [[1,2,3],[4,5,6],[7,8,9]]))
    <=>
    [1,4,7] : (transpose [[2,3],[5,6],[8,9]])
    <=>
    [1,4,7] : (map head [[2,3],[5,6],[8,9]]) : (transpose (map tail [[2,3],[5,6],[8,9]]))
    <=>
    [1,4,7] : [2,5,8] : (transpose [[3],[6],[9]])
    <=>
    [1,4,7] : [2,5,8] : (map head [[3],[6],[9]]) : (transpose (map tail [[3],[6],[9]]))
    <=>
    [1,4,7] : [2,5,8] : [3, 6, 9] : (transpose [[], [], []])
    <=>
    [1,4,7] : [2,5,8] : [3, 6, 9] : [] -- because transpose ([]:_) = []
    <=>
    [[1,4,7],[2,5,8],[3,6,9]]
    

    Note that the order in which I chose to reduce the terms, is not the same as the evaluation order haskell will use, but that does not change the result.

    Edit: In response to your edited question:

    is this

    (map head x)
    

    creating a list of the head elements of each list?

    Yes, it is.

    0 讨论(0)
  • 2021-02-12 07:36

    The cons operator : attach an object of type a to a list of type [a]. In

    (map head x) : transpose (map tail x)
    

    The LHS is a list (a = [b]), while the RHS is a list of list ([a] = [[b]]), so such a construction is valid. The result is

    [x,y,z,...] : [[a,b,...],[d,e,...],...] = [[x,y,z,...], [a,b,...],[d,e,...],...]
    

    In your case, map head x and map tail x splits the matrix

    x = [[1,2,3],[4,5,6],[7,8,9]]
    

    into

    map head x = [1,4,7]
    map tail x = [[2,3],[5,6],[8,9]]
    

    (and yes, map head x is a list of the head elements of each list.) The 2nd part is transposed (for detail steps see @sepp2k's answer) to form

    transpose (map tail x) = [[2,5,8],[3,6,9]]
    

    so cons-ing [1,4,7] to this gives

    map head x : transpose (map tail x) =  [1,4,7] : [[2,5,8],[3,6,9]]
                                        = [[1,4,7] ,  [2,5,8],[3,6,9]]
    
    0 讨论(0)
  • 2021-02-12 07:36

    ghci is your friend:

    *Main> :t map head
    map head :: [[a]] -> [a]
    *Main> :t map tail
    map tail :: [[a]] -> [[a]]

    Even if you don't understand map (a problem you'd want to correct quickly!), the types of these expressions tell much about how they work. The first is a single list taken from a list of lists, so let's feed a simple vector to it to see what happens.

    You might want to write

    *Main> map head [1,2,3]
    

    but that fails to typecheck:

    <interactive>:1:14:
        No instance for (Num [a])
          arising from the literal `3' at :1:14
        Possible fix: add an instance declaration for (Num [a])
        In the expression: 3
        In the second argument of `map', namely `[1, 2, 3]'
        In the expression: map head [1, 2, 3]

    Remember, the argument's type is a list of lists, so

    *Main> map head [[1,2,3]]
    [1]
    

    Getting a bit more complex

    *Main> map head [[1,2,3],[4,5,6]]
    [1,4]
    

    Doing the same but with tail instead of head gives

    *Main> map tail [[1,2,3],[4,5,6]]
    [[2,3],[5,6]]
    

    As you can see, the definition of transpose is repeatedly slicing off the first “row” with map head x and transposing the rest, which is map tail x.

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