Reputation: 401
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?
Upvotes: 0
Views: 127
Reputation: 8050
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],[⊥,⊥,⊥],...]
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
.
Upvotes: 4
Reputation: 12725
You can redefine the transpose
function in one line:
transpose = getZipList . traverse ZipList
All the definitions and instances are in the Control.Applicative
and Data.Traversable
modules. It's the same definition as in the Stefan Holdermans answer modulo typeclasses and wrapping-unwrapping stuff.
Upvotes: 0