{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
module FRP.Rhine.Schedule where
import Data.MonadicStreamFunction
import FRP.Rhine.Clock
data Schedule m cl1 cl2
= (TimeDomainOf cl1 ~ TimeDomainOf cl2)
=> Schedule
{ startSchedule
:: cl1 -> cl2
-> m (MSF m () (TimeDomainOf cl1, Either (Tag cl1) (Tag cl2)), TimeDomainOf cl1)
}
hoistSchedule
:: (Monad m1, Monad m2)
=> (forall a . m1 a -> m2 a)
-> Schedule m1 cl1 cl2
-> Schedule m2 cl1 cl2
hoistSchedule hoist Schedule {..} = Schedule startSchedule'
where
startSchedule' cl1 cl2 = hoist
$ first (hoistMSF hoist) <$> startSchedule cl1 cl2
hoistMSF = liftMSFPurer
flipSchedule
:: Monad m
=> Schedule m cl1 cl2
-> Schedule m cl2 cl1
flipSchedule Schedule {..} = Schedule startSchedule_
where
startSchedule_ cl2 cl1 = first (arr (second swapEither) <<<) <$> startSchedule cl1 cl2
swapEither :: Either a b -> Either b a
swapEither (Left a) = Right a
swapEither (Right b) = Left b
data SequentialClock m cl1 cl2
= TimeDomainOf cl1 ~ TimeDomainOf cl2
=> SequentialClock
{ sequentialCl1 :: cl1
, sequentialCl2 :: cl2
, sequentialSchedule :: Schedule m cl1 cl2
}
instance (Monad m, Clock m cl1, Clock m cl2)
=> Clock m (SequentialClock m cl1 cl2) where
type TimeDomainOf (SequentialClock m cl1 cl2) = TimeDomainOf cl1
type Tag (SequentialClock m cl1 cl2) = Either (Tag cl1) (Tag cl2)
startClock SequentialClock {..}
= startSchedule sequentialSchedule sequentialCl1 sequentialCl2
data ParallelClock m cl1 cl2
= TimeDomainOf cl1 ~ TimeDomainOf cl2
=> ParallelClock
{ parallelCl1 :: cl1
, parallelCl2 :: cl2
, parallelSchedule :: Schedule m cl1 cl2
}
instance (Monad m, Clock m cl1, Clock m cl2)
=> Clock m (ParallelClock m cl1 cl2) where
type TimeDomainOf (ParallelClock m cl1 cl2) = TimeDomainOf cl1
type Tag (ParallelClock m cl1 cl2) = Either (Tag cl1) (Tag cl2)
startClock ParallelClock {..}
= startSchedule parallelSchedule parallelCl1 parallelCl2
type family Leftmost cl where
Leftmost (SequentialClock m cl1 cl2) = Leftmost cl1
Leftmost (ParallelClock m cl1 cl2) = ParallelClock m (Leftmost cl1) (Leftmost cl2)
Leftmost cl = cl
type family Rightmost cl where
Rightmost (SequentialClock m cl1 cl2) = Rightmost cl2
Rightmost (ParallelClock m cl1 cl2) = ParallelClock m (Rightmost cl1) (Rightmost cl2)
Rightmost cl = cl
data LastTime cl where
SequentialLastTime
:: LastTime cl1 -> LastTime cl2
-> LastTime (SequentialClock m cl1 cl2)
ParallelLastTime
:: LastTime cl1 -> LastTime cl2
-> LastTime (ParallelClock m cl1 cl2)
LeafLastTime :: TimeDomainOf cl -> LastTime cl
data ParClockInclusion clS cl where
ParClockInL
:: ParClockInclusion (ParallelClock m clL clR) cl
-> ParClockInclusion clL cl
ParClockInR
:: ParClockInclusion (ParallelClock m clL clR) cl
-> ParClockInclusion clR cl
ParClockRefl :: ParClockInclusion cl cl
parClockTagInclusion :: ParClockInclusion clS cl -> Tag clS -> Tag cl
parClockTagInclusion (ParClockInL parClockInL) tag = parClockTagInclusion parClockInL $ Left tag
parClockTagInclusion (ParClockInR parClockInR) tag = parClockTagInclusion parClockInR $ Right tag
parClockTagInclusion ParClockRefl tag = tag