{-# LANGUAGE TypeOperators #-}
{-# OPTIONS -fplugin=Rattus.Plugin #-}
{-# LANGUAGE Arrows #-}
{-# LANGUAGE RebindableSyntax #-}
module Rattus.Yampa (
SF,
identity,
compose,
switch,
rSwitch,
constant,
loopPre,
stepSF,
initially,
integral,
(-->),
(-:>),
(>--),
(-=>),
(>=-),
(^>>),
(>>^),
(<<^),
(^<<),
module Rattus.Arrow, (>>>)) where
import Rattus.Primitives
import Rattus.Plugin
import Rattus.Strict
import GHC.Float
import Control.Category
import Rattus.Arrow
import Prelude hiding (id)
import Data.VectorSpace
{-# ANN module Rattus #-}
type DTime = Double
data SF a b = SF{
stepSF :: ! (DTime -> a -> (O(SF a b) :* b))}
identity :: SF a a
identity = SF (\ _ x -> (delay identity :* x))
compose :: SF b c -> SF a b -> SF a c
compose (SF sf2) (SF sf1) = SF sf
where sf d a = let (r1 :* b) = sf1 d a
(r2 :* c) = sf2 d b
in (delay (compose (adv r2) (adv r1)) :* c)
integral :: (Stable a, VectorSpace a s) => a -> SF a a
integral acc = SF sf'
where sf' t a = let acc' = acc ^+^ (realToFrac t *^ a)
in (delay (integral acc') :* acc')
switch :: SF a (b :* Maybe' c) -> Box (c -> SF a b) -> SF a b
switch (SF sf) f = SF sf'
where sf' t a = let (nxt :* (b :* c')) = sf t a
in case c' of
Just' c -> stepSF (unbox f c) t a
Nothing' -> (delay (switch (adv nxt) f):* b)
rSwitch :: SF a b -> SF (a :* Maybe' (SF a b)) b
rSwitch (SF sf) = SF sf'
where sf' t (a :* m) = case m of
Just' (SF newSf) ->
let (nxt :* b) = newSf t a
in (delay (rSwitch (adv nxt)) :* b)
Nothing' -> let (nxt :* b) = sf t a
in (delay (rSwitch (adv nxt)) :* b)
constant :: Stable b => b -> SF a b
constant x = run
where run = SF (\ _ _ -> (delay run :* x))
(-->) :: b -> SF a b -> SF a b
b --> (SF sf) = SF sf'
where sf' d x = (fst' (sf d x) :* b)
(-:>) :: b -> O (SF a b) -> SF a b
b -:> sf = SF sf'
where sf' _d _x = (sf :* b)
(>--) :: a -> SF a b -> SF a b
a >-- (SF sf) = SF sf'
where sf' d _a = sf d a
(-=>) :: (b -> b) -> SF a b -> SF a b
f -=> (SF sf) = SF sf'
where sf' d a = let (r:*b) = sf d a
in (r:*f b)
(>=-) :: (a -> a) -> SF a b -> SF a b
f >=- (SF sf) = SF sf'
where sf' d a = sf d (f a)
initially :: a -> SF a a
initially = (--> identity)
arrPrim :: Box (a -> b) -> SF a b
arrPrim f = run where
run = SF (\ _d a -> (delay run:* unbox f a ))
{-# ANN firstPrim AllowLazyData #-}
firstPrim :: SF a b -> SF (a,c) (b,c)
firstPrim (SF sf) = SF sf'
where sf' d (a,c) = let (r:* b) = sf d a
in (delay (firstPrim (adv r)):* (b,c))
{-# ANN secondPrim AllowLazyData #-}
secondPrim :: SF a b -> SF (c,a) (c,b)
secondPrim (SF sf) = SF sf'
where sf' d (c,a) = let (r:* b) = sf d a
in (delay (secondPrim (adv r)):* (c,b))
{-# ANN parSplitPrim AllowLazyData #-}
parSplitPrim :: SF a b -> SF c d -> SF (a,c) (b,d)
parSplitPrim (SF sf1) (SF sf2) = SF sf'
where sf' dt (a,c) = let (r1:* b) = sf1 dt a
(r2:* d) = sf2 dt c
in (delay (parSplitPrim (adv r1) (adv r2)):* (b,d))
{-# ANN parFanOutPrim AllowLazyData #-}
parFanOutPrim :: SF a b -> SF a c -> SF a (b, c)
parFanOutPrim (SF sf1) (SF sf2) = SF sf'
where sf' dt a = let (r1:* b) = sf1 dt a
(r2:* c) = sf2 dt a
in (delay (parFanOutPrim (adv r1) (adv r2)):* (b,c))
instance Category SF where
id = identity
(.) = compose
instance Arrow SF where
arrBox = arrPrim
first = firstPrim
second = secondPrim
(***) = parSplitPrim
(&&&) = parFanOutPrim
loopPre :: c -> SF (a:*c) (b:*O c) -> SF a b
loopPre c (SF sf) = SF sf'
where sf' d a = let (r:* (b:*c')) = sf d (a:*c)
in (delay (loopPre (adv c') (adv r)):* b)
(^>>) :: Arrow a => Box (b -> c) -> a c d -> a b d
f ^>> a = arrBox f >>> a
(>>^) :: Arrow a => a b c -> Box (c -> d) -> a b d
a >>^ f = a >>> arrBox f
(<<^) :: Arrow a => a c d -> Box (b -> c) -> a b d
a <<^ f = a <<< arrBox f
(^<<) :: Arrow a => Box (c -> d) -> a b c -> a b d
f ^<< a = arrBox f <<< a