2013-05-25 2 views
8

Понимание основных принципов Haskell (монады и так далее), но имеющих не использовали его за 2 года, я боролся в течение двух часов, чтобы сделать это маленькое упражнение чисто:Haskell: список разбит на 3-кортежей

Я хочу, чтобы преобразовать строку 3 * п целых чисел (как в "1 1 1 2 2 2 3 3 3") в список 3-кортежей Int (как в [(1,1,1),(2,2,2),(3,3,3)].

Это должно быть сделано в прямой вперед, ошибку выделяющегося пути .

Лучшее решение, которое я мог бы найти до сих пор, содержит следующее:

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 

Это не выглядит элегантным для меня. Как бы я закодировал эту функцию (с тем же интерфейсом) более точную?

ответ

8

Я действительно думаю, что ваше решение выглядит довольно хорошо. Однако, поскольку я не могу сопротивляться выбором цвета сарая, вы могли бы рассмотреть что-то вроде этого, тоже:

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

Вы также могли бы рассмотреть вопрос об использовании chunksOf:

import Control.Monad 
import Data.List.Split 
convert [x,y,z] = Just (x,y,z) 
convert _ = Nothing 
groupsOf3 = sequence . map convert . chunksOf 3 
+4

Или 'mapM новообращенными. chunksOf 3'. – hammar

+0

Отлично. Спасибо! –

Смежные вопросы