{-# LANGUAGE GADTs #-}{-# LANGUAGE Rank2Types #-}------------------------------------------------------------------------------- |-- Module : Data.Machine.Wye-- Copyright : (C) 2012 Edward Kmett, Rúnar Bjarnason, Paul Chiusano-- License : BSD-style (see the file LICENSE)---- Maintainer : Edward Kmett <ekmett@gmail.com>-- Stability : provisional-- Portability : Rank-2 Types, GADTs------------------------------------------------------------------------------moduleData.Machine.Wye(-- * WyesWye,WyeT,Y(..),wye,addX,addY,capX,capY)whereimportControl.CategoryimportData.Machine.ProcessimportData.Machine.TypeimportData.Machine.IsimportData.Machine.SourceimportPreludehiding((.),id)--------------------------------------------------------------------------------- Wyes--------------------------------------------------------------------------------- | The input descriptor for a 'Wye' or 'WyeT'dataYabcwhereX::Yaba-- block waiting on the left inputY::Yabb-- block waiting on the right inputZ::Yab(Eitherab)-- block waiting on either input-- | A 'Machine' that can read from two input stream in a non-deterministic manner.typeWyeabc=Machine(Yab)c-- | A 'Machine' that can read from two input stream in a non-deterministic manner with monadic side-effects.typeWyeTmabc=MachineTm(Yab)c-- | Compose a pair of pipes onto the front of a 'Wye'.-- | Precompose a 'Process' onto each input of a 'Wye' (or 'WyeT').---- This is left biased in that it tries to draw values from the 'X' input whenever they are-- available, and only draws from the 'Y' input when 'X' would block.wye::Monadm=>ProcessTmaa'->ProcessTmbb'->WyeTma'b'c->WyeTmabcwyemambm=MachineT$runMachineTm>>=\v->casevofYieldok->return$Yieldo(wyemambk)Stop->returnStopAwaitfXff->runMachineTma>>=\u->caseuofYieldak->runMachineT.wyekmb$faStop->runMachineT$wyestoppedmbffAwaitgReflfg->return.Await(\a->wye(ga)mb$encasedv)X.wyefgmb$encasedvAwaitfYff->runMachineTmb>>=\u->caseuofYieldbk->runMachineT.wyemak$fbStop->runMachineT$wyemastoppedffAwaitgReflfg->return.Await(\b->wyema(gb)$encasedv)Y.wyemafg$encasedvAwaitfZff->runMachineTma>>=\u->caseuofYieldak->runMachineT.wyekmb.f$LeftaStop->runMachineTmb>>=\w->casewofYieldbk->runMachineT.wyestoppedk.f$RightbStop->runMachineT$wyestoppedstoppedffAwaitgReflfg->return.Await(\b->wyestopped(gb)$encasedv)Y.wyestoppedfg$encasedvAwaitgReflfg->runMachineTmb>>=\w->casewofYieldbk->runMachineT.wye(encasedu)k.f$RightbStop->return.Await(\a->wye(ga)stopped$encasedv)X.wyefgstopped$encasedvAwaithReflfh->return.Await(\c->casecofLefta->wye(ga)(encasedw)$encasedvRightb->wye(encasedu)(hb)$encasedv)Z.wyefgfh$encasedv-- | Precompose a pipe onto the left input of a wye.addX::Monadm=>ProcessTmab->WyeTmbcd->WyeTmacdaddXp=wyepecho-- | Precompose a pipe onto the right input of a tee.addY::Monadm=>ProcessTmbc->WyeTmacd->WyeTmabdaddY=wyeecho-- | Tie off one input of a tee by connecting it to a known source.capX::Monadm=>SourceTma->WyeTmabc->ProcessTmbccapXst=process(cappedRight)(addXst)-- | Tie off one input of a tee by connecting it to a known source.capY::Monadm=>SourceTmb->WyeTmabc->ProcessTmaccapYst=process(cappedLeft)(addYst)-- | Natural transformation used by 'capX' and 'capY'capped::(a->Eitheraa)->Yaab->a->bcapped_X=idcapped_Y=idcappedfZ=f