moduleControl.Arrow.Transformer.Automaton.MaybewhereimportControl.ArrowimportqualifiedControl.CategoryasCimportControl.Arrow.OperationsimportqualifiedControl.Arrow.TransformerasATimportControl.Arrow.Transformer.AllimportData.MaybeimportqualifiedData.MapasM--A MaybeAutomaton returns either Just f to indicate a new Automaton,--or Nothing to indicate 'no change'/'do the same thing'.newtypeMaybeAutomatonaio=MaybeAutomaton(ai(o,Maybe(Automatonaio)))mAut(MaybeAutomatonf)=fautomatonFromMaybef=Automaton(mAutf>>>second(arr(fromMaybe(automatonFromMaybef))))maybeFromAutomaton(Automatonf)=MaybeAutomaton(f>>>second(arrJust))--Why use MaybeAutomata? The arrow instances coalesce Nothings,--reducing memory use.instance(Arrowa)=>C.Category(MaybeAutomatona)where(.)fg=MaybeAutomaton$(mAutg)>>>(mAutf***arrid)>>>arr(\((o,f'),g')->(o,case(f',g')of(Nothing,Nothing)->Nothing(_,_)->Just$fromMaybe(automatonFromMaybef)f'C..fromMaybe(automatonFromMaybeg)g'))id=MaybeAutomaton(C.id>>>arr(flip(,)Nothing))instance(Arrowa)=>Arrow(MaybeAutomatona)wherearrf=MaybeAutomaton(arrf>>>arr(flip(,)Nothing))(***)fg=MaybeAutomaton$(mAutf***mAutg)>>>arr(\((o1,f'),(o2,g'))->((o1,o2),case(f',g')of(Nothing,Nothing)->Nothing(_,_)->Just$fromMaybe(automatonFromMaybef)f'***fromMaybe(automatonFromMaybeg)g'))firstf=f***arridsecondf=arrid***finstance(ArrowChoicea)=>ArrowChoice(MaybeAutomatona)where(+++)fg=MaybeAutomaton$mAutf+++mAutg>>>arr(\x->casexofLeft(o,f')->(Lefto,fmap(+++automatonFromMaybeg)f')Right(o,g')->(Righto,fmap(automatonFromMaybef+++)g'))leftf=f+++arridrightf=arrid+++f