-- |-- Module: FRP.NetWire.Switch-- Copyright: (c) 2011 Ertugrul Soeylemez-- License: BSD3-- Maintainer: Ertugrul Soeylemez <es@ertes.de>---- Switching combinators. Note that 'Wire' also provides a-- state-preserving 'Control.Arrow.ArrowApply' instance, which may be-- more convenient than these combinators in many cases.moduleFRP.NetWire.Switch(-- * Basic switchesswitch,dSwitch,rSwitch,drSwitch,-- * BroadcastersparB,rpSwitchB,drpSwitchB,-- * Routerspar,rpSwitch,drpSwitch)whereimportqualifiedData.TraversableasTimportControl.ApplicativeimportData.Traversable(Traversable)importFRP.NetWire.Wire-- | Decoupled variant of 'rpSwitch'.drpSwitch::(Applicativem,Monadm,Traversablef)=>(forallw.a->fw->f(b,w))->f(Wirembc)->Wirem(a,Maybe(f(Wirembc)->f(Wirembc)))(fc)drpSwitchroutewires'''=WGen$\ws(x'',ev)->doletwires''=routex''wires'''r<-T.sequenceA$fmap(\(x',w')->toGenw'wsx')wires''letxs=T.sequenceA.fmapfst$rwires'=fmapsndrwires=maybeididevwires'return(xs,rpSwitchroutewires)-- | Decoupled variant of 'rpSwitchB'.drpSwitchB::(Applicativem,Monadm,Traversablef)=>f(Wiremab)->Wirem(a,Maybe(f(Wiremab)->f(Wiremab)))(fb)drpSwitchBwires''=WGen$\ws(x',ev)->dor<-T.sequenceA$fmap(\w'->toGenw'wsx')wires''letxs=T.sequenceA.fmapfst$rwires'=fmapsndrwires=maybeididevwires'return(xs,rpSwitchBwires)-- | Decoupled variant of 'rSwitch'.drSwitch::Monadm=>Wiremab->Wirem(a,Maybe(Wiremab))bdrSwitchw1'=WGen$\ws(x',swEv)->do(mx,w1)<-toGenw1'wsx'letw=maybew1idswEvw`seq`return(mx,drSwitchw)-- | Decoupled variant of 'switch'.dSwitch::Monadm=>Wirema(b,Maybec)->(c->Wiremab)->WiremabdSwitchw1'f=WGen$\wsx'->do(m,w1)<-toGenw1'wsx'casemofLeftex->return(Leftex,dSwitchw1f)Right(x,swEv)->caseswEvofNothing->return(Rightx,dSwitchw1f)Justsw->return(Rightx,fsw)-- | Route signal to a collection of signal functions using the supplied-- routing function. If any of the wires inhibits, the whole network-- inhibits.par::(Applicativem,Monadm,Traversablef)=>(forallw.a->fw->f(b,w))->f(Wirembc)->Wirema(fc)parroutewires''=WGen$\wsx''->doletwires'=routex''wires''r<-T.sequenceA$fmap(\(x',w')->toGenw'wsx')wires'letxs=T.sequenceA.fmapfst$rwires=fmapsndrreturn(xs,parroutewires)-- | Broadcast signal to a collection of signal functions. If any of-- the wires inhibits, then the whole parallel network inhibits.parB::(Applicativem,Monadm,Traversablef)=>f(Wiremab)->Wirema(fb)parBwires'=WGen$\wsx'->dor<-T.sequenceA$fmap(\w'->toGenw'wsx')wires'letxs=T.sequenceA.fmapfst$rwires=fmapsndrreturn(xs,parBwires)-- | Recurrent parallel routing switch. This combinator acts like-- 'par', but takes an additional event signal, which can transform the-- set of wires. This is the most powerful switch.---- Just like 'par' if any of the wires inhibits, the whole network-- inhibits.rpSwitch::(Applicativem,Monadm,Traversablef)=>(forallw.a->fw->f(b,w))->f(Wirembc)->Wirem(a,Maybe(f(Wirembc)->f(Wirembc)))(fc)rpSwitchroutewires'''=WGen$\ws(x'',ev)->doletwires''=maybeididevwires'''wires'=routex''wires''r<-T.sequenceA$fmap(\(x',w')->toGenw'wsx')wires'letxs=T.sequenceA.fmapfst$rwires=fmapsndrreturn(xs,rpSwitchroutewires)-- | Recurrent parallel broadcast switch. This combinator acts like-- 'parB', but takes an additional event signal, which can transform the-- set of wires.---- Just like 'parB' if any of the wires inhibits, the whole network-- inhibits.rpSwitchB::(Applicativem,Monadm,Traversablef)=>f(Wiremab)->Wirem(a,Maybe(f(Wiremab)->f(Wiremab)))(fb)rpSwitchBwires''=WGen$\ws(x',ev)->doletwires'=maybeididevwires''r<-T.sequenceA$fmap(\w'->toGenw'wsx')wires'letxs=T.sequenceA.fmapfst$rwires=fmapsndrreturn(xs,rpSwitchBwires)-- | Combinator for recurrent switches. The wire produced by this-- switch takes switching events and switches to the wires contained in-- the events. The first argument is the initial wire.rSwitch::Monadm=>Wiremab->Wirem(a,Maybe(Wiremab))brSwitchw1=WGen$\ws(x',swEv)->doletw'=maybew1idswEv(mx,w)<-toGenw'wsx'return(mx,rSwitchw)-- | This is the most basic switching combinator. It is an event-based-- one-time switch.---- The first argument is the initial wire, which may produce a switching-- event at some point. When this event is produced, then the signal-- path switches to the wire produced by the second argument function.switch::Monadm=>Wirema(b,Maybec)->(c->Wiremab)->Wiremabswitchw1'f=WGen$\wsx'->do(m,w1)<-toGenw1'wsx'casemofLeftex->return(Leftex,switchw1f)Right(x,swEv)->caseswEvofNothing->return(Rightx,switchw1f)Justsw->toGen(fsw)(ws{wsDTime=0})x'