Skip to content

Instantly share code, notes, and snippets.

@cschneid
Last active August 29, 2015 14:18
Show Gist options
  • Save cschneid/f0cc220552a5bb8c193e to your computer and use it in GitHub Desktop.
Save cschneid/f0cc220552a5bb8c193e to your computer and use it in GitHub Desktop.
module Grocery.Calendar where
import Data.Time
import Grocery.Types.Meal
import Control.Lens
import Data.Ord
import Data.List (sortBy)
type Calendar = [(Day, [Meal])]
createMealCalendar :: [Meal] -> Calendar
createMealCalendar [] = []
createMealCalendar meals = createMealCalendar' [] [firstDay..lastDay] sortedMeals
where
firstDay = (head meals) ^. day
lastDay = (last meals) ^. day
sortedMeals = sortBy (comparing (^. day)) meals
-- first case, empty calendar, create the first day & meal
createMealCalendar' [] dds@(d:ds) (m:ms) = createMealCalendar' [(d, [m])] dds ms
-- base case, when we run out of meals to add, we're done
createMealCalendar' cal _ [] = cal
-- base case, when we run out of days, something odd happened
createMealCalendar' _ [] _ = error "Ran out of days!?"
-- recursive case. init & last are safe due to previous check.
createMealCalendar' cal dds@(d:ds) mms@(m:ms) = -- if this meal belongs on this day, add it and recurse
if m ^. day == d
then let previousCal = init cal
previousMealList = (snd . last) cal
updatedDay = (d, previousMealList ++ [m])
newCal = previousCal ++ [updatedDay]
in createMealCalendar' newCal dds ms
-- Advance one day when the meal doesn't belong
else let newCal = (cal ++ [(d, [])])
in createMealCalendar' newCal ds mms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment