Reputation: 41
I am trying to set up some functions to help with a current project I am working on. I am new to Haskell and struggling to implement my desired functions.
I have a list [a]
and would like it to output a tuple of four different lists ([b],[b],[b],[b])
where each item in list [a]
is successively placed in to the next list in the output tuple. So the first element in the input list [a]
goes to the first list [b]
, the second element in [a]
goes to the second list [b]
, the third element in [a]
goes to the third list [b]
, and so on.
I have tried using chunksOf and splitEvery/splitAt but cannot get the correct output. And help would be greatly appreciated! Thanks!
Upvotes: 3
Views: 588
Reputation: 3504
Define
f n = transpose . chunksOf n
g xs = let [xs1, xs2, xs3, xs4] = f 4 xs in (xs1, xs2, xs3, xs4)
Where f
is the general solution. This gives
Prelude> g ['a' .. 'z']
("aeimquy","bfjnrvz","cgkosw","dhlptx")
Signatures
Prelude> :t g
g :: [a] -> ([a], [a], [a], [a])
and
Prelude> :t f
f :: Int -> [a] -> [[a]]
Info on:
Upvotes: 3
Reputation: 476584
You each time "rotate" the 4-tuple and prepend to the first element. So we can implement this with a foldr
pattern that looks like:
toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (\a (bs, cs, ds, as) -> (a:as, bs, cs, ds)) ([], [], [], [])
or with an irrefutable pattern:
toFour :: [a] -> ([a], [a], [a], [a])
toFour = foldr (\a ~(bs, cs, ds, as) -> (a:as, bs, cs, ds)) ([], [], [], [])
So here (bs, cs, ds, as)
is the 4-tuple that we generated for the tail of the list, and we "rotate" to the right to construct the tuple (as, bs, cs, ds)
and then prepend the item a
to the first list of the 4-tuple.
For a list of integers, this gives us:
Prelude> toFour [1..2]
([1],[2],[],[])
Prelude> toFour [1..3]
([1],[2],[3],[])
Prelude> toFour [1..4]
([1],[2],[3],[4])
Prelude> toFour [1..5]
([1,5],[2],[3],[4])
Prelude> toFour [1..6]
([1,5],[2,6],[3],[4])
Prelude> toFour [1..10]
([1,5,9],[2,6,10],[3,7],[4,8])
When we work with the irrefutable pattern, this is done lazily, so we can for example distribute elements of an infinite list, and then take for example obtain the first 10 elements of the second item:
Prelude> (\(_, l, _, _) -> take 10 l) (toFour [1..])
[2,6,10,14,18,22,26,30,34,38]
Upvotes: 7