From aea8a111a760886536b461b8d74175a4d9433b94 Mon Sep 17 00:00:00 2001 From: Josef Svenningsson Date: Mon, 10 Jun 2019 07:17:40 -0700 Subject: [PATCH] Use a more stack efficient version of mapM The function mapM is notorious for eating up a lot of stack space. This diff provides a version of mapM for the Maybe monad and the list traversable which doesn't eat up the stack. Having a version of mapM which doesn't eat a lot of stack is particularly helpful when trying to find spaceleaks with the method described here: http://neilmitchell.blogspot.com/2015/09/detecting-space-leaks.html --- Data/Time/LocalTime/TimeZone/Olson/Parse.hs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Data/Time/LocalTime/TimeZone/Olson/Parse.hs b/Data/Time/LocalTime/TimeZone/Olson/Parse.hs index 18d32e0..84bfb9d 100644 --- a/Data/Time/LocalTime/TimeZone/Olson/Parse.hs +++ b/Data/Time/LocalTime/TimeZone/Olson/Parse.hs @@ -60,7 +60,7 @@ instance Exception OlsonError -- | Convert parsed Olson timezone data into a @TimeZoneSeries@. olsonToTimeZoneSeries :: OlsonData -> Maybe TimeZoneSeries olsonToTimeZoneSeries (OlsonData ttimes ttinfos@(dflt0:_) _ _) = - fmap (TimeZoneSeries $ mkTZ dflt) . mapM (lookupTZ ttinfos) . + fmap (TimeZoneSeries $ mkTZ dflt) . mapMMaybe (lookupTZ ttinfos) . uniqTimes . sortBy futureToPast $ ttimes where dflt = fromMaybe dflt0 . listToMaybe $ filter isStd ttinfos @@ -74,6 +74,16 @@ olsonToTimeZoneSeries (OlsonData ttimes ttinfos@(dflt0:_) _ _) = futureToPast = comparing $ negate . transTime olsonToTimeZoneSeries _ = Nothing +mapMMaybe :: (a -> Maybe b) -> [a] -> Maybe [b] +mapMMaybe f ls = mapMCont f ls [] + +mapMCont :: (a -> Maybe b) -> [a] -> [b] -> Maybe [b] +mapMCont f [] acc = Just (reverse acc) +mapMCont f (x:xs) acc = + case f x of + Nothing -> Nothing + Just x -> mapMCont f xs (x:acc) + -- | Read timezone data from a binary Olson timezone file and convert -- it into a @TimeZoneSeries@ for use together with the types and -- fucntions of "Data.Time". This is the function from this module