Search code examples
listhaskellhead

Something wrong with a Haskell List


I do not know what happened with this. I have a list L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

and i need a function that gives me this: L = [[1, 4, 7],[2, 5, 8],[3, 6, 9]]

until now i have this:

rotar2 [ ] = [ ]
rotar2 l = [map head l] ++ rotar2(map tail l)

and it works but not at all.. it sends me this error:

[[1,4,7],[2,5,8],[3,6,9],[ Program error: pattern match failure: head []

what should i do?


Solution

  • You are repeatedly taking the heads and tails of every list in your function's input. Eventually, one of these lists will only have the empty list left as a tail and attempting to take the head of that empty list will then fail.

      rotar2 [[1,2,3],[4,5,6],[7,8,9]]
        = [[1,4,7]] ++ rotar2 [[2,3], [5,6], [8,9]]
        = [[1,4,7]] ++ [[2,5,8]] ++ rotar2 [[3], [6], [9]]
        = [[1,4,7]] ++ [[2,5,8]] ++ [[3,6,9]] ++ rotar2 [[],[],[]]
        = [[1,4,7]] ++ [[2,5,8]] ++ [[3,6,9]] ++ [head [],head[],head []] ++ ...
        = [[1,4,7],[2,5,8],[3,6,9],[⊥,⊥,⊥],...]
    

    Transpose

    The function rotar2 that you are trying to define is usually called transpose and can be implemented rather straightforwardly as

    transpose :: [[a]] -> [[a]]
    transpose []         = repeat []
    transpose (xs : xss) = zipWith (:) xs (transpose xss)
    

    The idea is that a nonempty list of lists, say [[1,2,3],[4,5,6],[7,8,9]], can be transposed inductively by first transposing its tail [[4,5,6],[7,8,9]], yielding [[4,7],[5,8],[6,9]], and then prepending the elements of the head list [1,2,3] to the elements of the transposed tail:

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

    Hence:

    > transpose [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    [[1,4,7],[2,5,8],[3,6,9]]
    

    In the standard libraries, this function is exported by the module Data.List.