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







Reply via email to