Hallo,
reading in a 2-dimensional table that was stored row-wise
to get the data column-wise I used 'transpose'
to use the data column-wise.
Reading only the head of a columm resulted in reading the
complete (very big) table, because transpose was not as much
lazy as I wished.
transpostion of a indefinite matrix is looping
head (head (transpose (reapeat [1..])))
Looking at the code I think it was blocked in the
zipWith waiting for the 'b'-pattern.
transpose :: [[a]] -> [[a]]
transpose = foldr
(\xs xss -> zipWith (:) xs (xss ++ repeat []))
[]
zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith z (a:as) (b:bs)
= z a b : zipWith z as bs
zipWith _ _ _ = []
It helped to use a lazy pattern in a modified zipWith:
transpose' :: [[a]] -> [[a]]
transpose' =
foldr
(\xs xss -> zipWith' (:) xs (xss ++ repeat []))
[]
where
zipWith' z (a:as) ~(b:bs) = z a b : zipWith' z as bs
zipWith' _ _ _ = []
But still non-rectangular matrixes are cutted:
transpose' [[1,2],[3,4,5]] = [[1,3],[2,4]]
or the irrefutable pattern fails for
transpose' [[1,2],[3,4,5],[]] = fail
this helps:
transpose'' :: [[a]] -> [[a]]
transpose'' ([]:rs) = transpose'' rs
transpose'' ((x:xs):rs) =
(x:(map head rs')):(transpose'' (xs:(map tail rs')))
where rs' = filter ((/=)[])) rs
transpose'' _ = []
transpose'' [[1,2],[3,4,5]] = [[1,3],[2,4],[5]]
head (head (transpose'' (reapeat [1..]))) = 1
is there anybody out that has a smarter solution ?
Klemens