I am working on a haskell exercise where I have to compute the amount of people riding a rollercoaster in a day. I have the following data: the number of rides in a day, the number of seats, and the composition of the queue.
The queue is a list of groups. During each ride, the first few groups of the list enter the ride. A group always rides together. The total number of people cannot exceed the number of seat during one ride.
After the ride, the groups go to the end of the queue (in the same order).
So the exercise is not really hard. But when numbers get big, my haskell implementation becomes quite slow. I have used the profiler to improve some parts, but I wasn't able to spot a bottleneck.
The first time I ran the profiler, the part that was parsing the groups was slow. Here is my second version (1st one was
replicateM n $ read <$> getLine):
getGroups :: IO [Int] getGroups = do c <- TIO.getContents return $ readInts c readInts :: T.Text -> [Int] readInts s | T.null s =  | otherwise = val : rest where (Right (val, s')) = TR.decimal s rest = if T.null s' then  else (readInts $ T.tail s')
Another cost center is the actual computing function:
type Queue = Seq.Seq Int data Roller = Roller Int Int Queue compEarn :: Roller -> Int compEarn (Roller placeNbr rideNbr groups) = go rideNbr groups 0 where go turnsLeft queue accum | turnsLeft == 0 = accum | otherwise = let (riding, waiting) = breakQueue placeNbr queue newQueue = waiting Seq.>< riding newAccum = accum + (F.sum riding) in go (turnsLeft - 1) newQueue newAccum breakQueue :: Int -> Queue -> (Queue, Queue) breakQueue placeNbr queue = go Seq.empty queue placeNbr where go riding waiting spaceLeft = case Seq.viewl waiting of Seq.EmptyL -> (riding, waiting) group Seq.:< rest -> if spaceLeft' < 0 then (riding, waiting) else go (riding Seq.|> group) rest spaceLeft' where spaceLeft' = spaceLeft - group
Am I missing something obvious regarding performances with this program?