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?
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With