Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell which function to group list every n such that :: [a] -> Int -> [[a]]

I'm sure there's a simple function to do this, it should:

> groupEvery [1,2,3,4,5,6] 2
[[1,2],[3,4],[5,6]]

I just don't know off hand and hoogle was no help..

like image 981
Jimmy Hoffa Avatar asked Dec 03 '22 22:12

Jimmy Hoffa


1 Answers

I don't know of any built-in function for that, but it can be implemented easily:

slice :: Int -> [a] -> [[a]]
slice _ [] = []
slice n xs = hs : slice n ts
  where (hs, ts) = splitAt n xs

It repeatedly splits its input to first n elements and the rest. Or, using unfoldr from Data.List:

slice n = unfoldr (\xs -> if null xs then Nothing 
                                     else Just (splitAt n xs))

Update: Just for fun I tried to make as short version as possible using standard functions. So far I've got

import Data.Functor ((<$))
import Data.List (unfoldr)
import Data.Maybe (listToMaybe)

slice :: Int -> [a] -> [[a]]
slice n = unfoldr (\xs -> splitAt n xs <$ listToMaybe xs)

using <$ from Maybe's instance of Functor. Or slightly shorter but even less comprehensible using Applicative for (->) [a]:

slice n = unfoldr (liftA2 (<$) (splitAt n) listToMaybe)
slice n = unfoldr ((<$) <$> splitAt n <*> listToMaybe)

The most incomprehensible version of my attempts was

import Control.Monad.Trans
import Control.Monad.Trans.Maybe
slice n = unfoldr (runMaybeT ((MaybeT listToMaybe) >> (lift $ splitAt n)))
like image 138
Petr Avatar answered Apr 27 '23 15:04

Petr