
Hi all, If I have a list, and I'd like to convert it to a list of lists, each of length n, I can use a function like bunch: bunch _ [] = [] bunch n as = let (c,cs) = splitAt n as in c:bunch n cs
bunch 8 [1..16] [[1,2,3,4,5,6,7,8],[9,10,11,12,13,14,15,16]]
If I now want to do the same for the nested lists, I can compose an application involving both map and bunch:
map (bunch 4) . bunch 8 $ [1..16] [[[1,2,3,4],[5,6,7,8]],[[9,10,11,12],[13,14,15,16]]]
and I can "bunch" the new length 4 lists again:
map (map (bunch 2)) . map (bunch 4) . bunch 8 $ [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
Clearly there is a pattern here involving the bunch function and latterly, three Int parameters; 2, 4 and 8. My question is, can I create a function that will take such parameters as a list, and give the same result, for example:
f [2,4,8] [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
or perhaps:
f [bunch 2, bunch 4, bunch 8] [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
I think it may not be possible because the type signature of f would depend on the length of its list parameter; but I'm not sure. -Paul

Hi Paul, I don't have time to solve your actual problem, but I think it's doable using associated type families. I attach a module which I'm using in my current project that does things quite similar to what you're asking for. For example: *Main> replicateArray (3 :> IntArr) 4 [4,4,4] *Main> replicateArray (4 :> 3 :> IntArr) 4 [[4,4,4],[4,4,4],[4,4,4],[4,4,4]] Hope it helps! / Emil Paul Keir skrev:
Hi all,
If I have a list, and I'd like to convert it to a list of lists, each of length n, I can use a function like bunch:
bunch _ [] = [] bunch n as = let (c,cs) = splitAt n as in c:bunch n cs
bunch 8 [1..16] [[1,2,3,4,5,6,7,8],[9,10,11,12,13,14,15,16]]
If I now want to do the same for the nested lists, I can compose an application involving both map and bunch:
map (bunch 4) . bunch 8 $ [1..16] [[[1,2,3,4],[5,6,7,8]],[[9,10,11,12],[13,14,15,16]]]
and I can "bunch" the new length 4 lists again:
map (map (bunch 2)) . map (bunch 4) . bunch 8 $ [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
Clearly there is a pattern here involving the bunch function and latterly, three Int parameters; 2, 4 and 8. My question is, can I create a function that will take such parameters as a list, and give the same result, for example:
f [2,4,8] [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
or perhaps:
f [bunch 2, bunch 4, bunch 8] [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
I think it may not be possible because the type signature of f would depend on the length of its list parameter; but I'm not sure.
-Paul
------------------------------------------------------------------------
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

How about... *Main> bunch () [1..16] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] *Main> bunch (8 :+: ()) [1..16] [[1,2,3,4,5,6,7,8],[9,10,11,12,13,14,15,16]] *Main> bunch (8 :+: 4 :+: ()) [1..16] [[[1,2,3,4],[5,6,7,8]],[[9,10,11,12],[13,14,15,16]]] *Main> bunch (8 :+: 4 :+: 2 :+: ()) [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]] Here's the hack :)
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TypeFamilies #-}
infixr 6 :+: data Bunch b = Int :+: b
class Bunchable b a where type Bunched b a :: * bunch :: b -> [a] -> Bunched b a
instance Bunchable () a where type Bunched () a = [a] bunch () = id
instance Bunchable b a => Bunchable (Bunch b) a where type Bunched (Bunch b) a = [Bunched b a] bunch (n :+: r) = map (bunch r) . simpleBunch n
simpleBunch :: Int -> [a] -> [[a]] simpleBunch _ [] = [] simpleBunch n as = let (c,cs) = splitAt n as in c:simpleBunch n cs
The key here is that 'Bunch' reflects its lenght on its type, but '[]' doesn't. It may be possible to keep using a list, but it would be very ugly, I guess. -- Felipe.

On Thu, 4 Jun 2009, Paul Keir wrote:
Hi all,
If I have a list, and I'd like to convert it to a list of lists, each of length n, I can use a function like bunch:
bunch _ [] = [] bunch n as = let (c,cs) = splitAt n as in c:bunch n cs
http://hackage.haskell.org/packages/archive/utility-ht/0.0.5.1/doc/html/Data...
bunch 8 [1..16] [[1,2,3,4,5,6,7,8],[9,10,11,12,13,14,15,16]]
If I now want to do the same for the nested lists, I can compose an application involving both map and bunch:
map (bunch 4) . bunch 8 $ [1..16] [[[1,2,3,4],[5,6,7,8]],[[9,10,11,12],[13,14,15,16]]]
and I can "bunch" the new length 4 lists again:
map (map (bunch 2)) . map (bunch 4) . bunch 8 $ [1..16] [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
Don't you first break the list into 2-element lists, then the resulting list into 2-element lists and so on? I.e. bunch 2 . bunch 2 . bunch 2 $ [1..16] Calling 'bunch' multiple times is problematic since every call has a different signature, a different depth of list nesting. I guess you have to use a tree type, which allows arbitrary list nesting at run-time.
participants (4)
-
Emil Axelsson
-
Felipe Lessa
-
Henning Thielemann
-
Paul Keir