Reputation:
The following example is a simplification of the problem.
I have a list [Either Foo Bar]
,and another list [Biz]
.
The idea is that I iterate each Biz
element through [Either Foo Bar]
,from the beginning of the [Either Foo Bar]
, until Biz
is empty. The result will be that there will now be more Bar
s and less Foo
s in the [Either Foo Bar]
The problem is being able to start at the beginning of [Either Foo Bar]
when it's time to use the next element in [Biz]
.
I could post an example of what I am trying to do, if it will help.
Update: Okay here are the actual types I am using, still trying to leave out what I think may be extraneous information. Please let me know if I have left out something important
[Either UnFlaggedDay CalendarDay]
[(CalFlag,Product, Day)]
data CalFlag = FirstPass | SecondPass | ThirdPass deriving (Enum,Eq,Show)
What I'm trying to do is check the Day
against the Left
value in [Either UnFlaggedDay CalendarDay]
. When I get a match, I want make a new list, that is exactly the same excepting the following changes : I will change that UnFlaggedDay
, plus the next two UnflaggedDay
s in the list to CalendarDay
s. At that point, I want to use the newly built list, that has the same number of elements still, and the
[(CalFlag,Product, Day)]minus the
(CalFlag,Product, Day)` that was just checked against. Below is some broken code that is in between my different approaches to this problem.
flagReserved :: [Either UnFlaggedDay CalendarDay] -> Handler [Either UnFlaggedDay CalendarDay] flagReserved ((Left (MkUFD day)):rest) = do reserved <- runDB $ selectList [TestQueue ==. Scheduled_Q, TestStatus /<-. [Passed,Failed]] [] case (L.null reserved) of True -> do processedDays <- ((Left $ MkUFD day) :) <$> flagReserved rest return processedDays False -> return $ flagReserved' (map prepList ((Left (MkUFD day)):rest)) (flagProductTuple reserved) flagReserved ((Right (MkCal day)):rest) = do processedDays <- ((Right $ MkCal day):) <$> flagReserved rest return processedDays flagReserved _ = return [] flagReserved' :: [Either (UnFlaggedDay) CalendarDay] -> [(CalFlag,Product,Maybe C.Day)] -> [Either UnFlaggedDay CalendarDay] flagReserved' ((Left (MkUFD day)):restD) ((calFlag,firmware,Just startDate):restF) = case (startDate == day || not (calFlag == FirstPass)) of True | (calFlag == ThirdPass) -> flagReserved' ((Right $ conScheduled day firmware Reserved) : restD) restF | otherwise -> flagReserved (Right $ consScheduled day firmware Reserved) : flagReserved' restD ((succ calFlag, firmware, Just startDate) : restF) False -> (Left (MkUFD day)) : flagReserved' restD ((calFlag, firmware, Just startDate) : restF) flagReserved' ((Right (MkCal (Left (MkAD (dayText,day))))):restD) ((calFlag,firmware,Just startDate):restF) = case (startDate == day || not (calFlag == FirstPass)) of True | (calFlag == ThirdPass) -> (Right $ consScheduled day firmware Reserved) : flagReserved' restD restF | otherwise -> (Right $ consScheduled day firmware Reserved) : flagReserved' restD ((succ calFlag, firmware, Just startDate):restF) False -> (Right (MkCal (Left (MkAD (dayText,day))))) : flagReserved' restD ((calFlag,firmware,Just startDate) : restF) flagReserved' ((Right (MkCal (Right unAvailable))):restD) ((calFlag,firmware,startDate):restF) = (Right $ MkCal $ Right unAvailable) : flagReserved' restD ((calFlag,firmware,startDate) : restF) flagReserved' unprocessed [] = unprocessed flagReserved' [] _ = []
Update:
I've made some test code to work out my thoughts. Here's what I have so far
let reservedDays = [(FirstPass,IM,C.fromGregorian 2012 01 15), (FirstPass,WAF,C.fromGregorian 2012 01 14), (FirstPass,Backup,C.fromGregorian 2012 01 13) ] dummyFunc :: [Either UnFlaggedDay CalendarDay] -> (CalFlag,Product,C.Day) dummyFunc dayList (cFlag,product,day) = if day `elem` dayList then dummyFunc' dayList (cFlag,product,day) else dayList dummyFunc' dayList (cFlag,product,day) = if (cFlag == ThirdPass) then
Okay here is where I am stuck. I need to be able to change the next three Left values to Right values. My intent for dummyFunc'
was to split the list at the first Left
Value, remove it, add the new Right
value, join the previously split lists, and repeat two more times. Is there a better way? If not, is there already a function that will split a list in half based on the criteria I mentioned? I can figure out how to do it by hand, but I'm not trying to reinvent the wheel.
Upvotes: 0
Views: 121
Reputation: 64740
I take it that each element in the [Biz]
might adjust one or more elements in the [Either Foo Bar]
away from the left (Foo
) type and to the right (Bar
) type. This is just a fold:
eitherList = [Left (), Left (), Right 5, Right 9, Left ()]
bizList = [4,5,6,7,1]
func eitherlst biz = if (Left ()) `elem` eitherlst
then Right biz : delete (Left ()) eitherlst
else eitherlst
eitherList' = foldl func eitherList bizList
The above is untested, but you can see how the updated eitherList
is passed between each call to func
as a result of considering the original eitherList
and all Biz
elements up to that point. As you can see, your implementation of func
is what will make this useful.
Upvotes: 1