Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: split list into 3-tuples

Tags:

haskell

Understanding the basic principles of Haskell (Monads and so forth), but having not used it for 2 years, I have been struggling for two hours to do this little exercise cleanly:

I want to convert a line of 3*n integers (as in "1 1 1 2 2 2 3 3 3") to a list of 3-tuples of Int (as in [(1,1,1),(2,2,2),(3,3,3)].

This should be done in a straight-forward, error-catching way.

The best solution I could come up with so far contains the following:

groupsOf3 :: [a] -> Maybe [(a,a,a)]
groupsOf3 list =
    let fun l = case l of
            []           -> []
            (x:y:z:rest) -> (Just (x,y,z)) : (fun rest)
            _            -> [Nothing]
    in sequence $ fun list

That does not seem elegant to me. How would I code this function (with the same interface) more to-the-point?

like image 369
Jo So Avatar asked May 25 '13 01:05

Jo So


1 Answers

I actually think your solution looks pretty good. However, because I can't resist choosing shed colors, you might consider something like this, too:

import Control.Applicative
import Control.Monad
groupsOf3 (x:y:z:rest) = ((x,y,z):) <$> groupsOf3 rest
groupsOf3 smallList    = guard (null smallList) >> return []

You could also consider using chunksOf:

import Control.Monad
import Data.List.Split
convert [x,y,z] = Just (x,y,z)
convert _ = Nothing
groupsOf3 = sequence . map convert . chunksOf 3
like image 82
Daniel Wagner Avatar answered Oct 24 '22 01:10

Daniel Wagner