packages feed

WidgetRattus-0.1: src/AsyncRattus/Future.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS -fplugin=AsyncRattus.Plugin #-}


-- | Programming with futures.

module AsyncRattus.Future
  ( F(..)
  , SigF(..)
  , mkSigF
  , mkSigF'
  , current
  , future
  , bindF
  , mapF
  , sync
  , syncF
  , switchAwait
  , switch
  , switchS
  , filterMap
  , filterMapAwait
  , filterAwait
  , filter
  , trigger
  , triggerAwait
  , map
  , mapAwait
  , zipWith
  , zipWithAwait
  , fromSig
  , scan
  , scanAwait
  )

where

import AsyncRattus
import AsyncRattus.Signal (Sig(..))
import Prelude hiding (map, filter, zipWith)
import AsyncRattus.Channels

newtype OneShot a = OneShot (F a)

instance Producer (OneShot a) a where
  getCurrent (OneShot (Now x)) = Just' x
  getCurrent (OneShot (Wait _)) = Nothing'

  getNext (OneShot (Now _)) cb = cb (never :: O (OneShot a))
  getNext (OneShot (Wait x)) cb = cb (delay (OneShot (adv x)))

instance Producer p a => Producer (F p) a where
  getCurrent (Now x) = getCurrent x
  getCurrent (Wait _) = Nothing'
  
  getNext (Now x) cb = getNext x cb
  getNext (Wait x) cb = cb x

instance Producer (SigF a) a where
  getCurrent (x :>: _) = Just' x
  getNext (_ :>: xs) cb = cb xs



-- | @F a@ will produces a value of type @a@ after zero or more ticks
-- of some clocks
data F a = Now !a | Wait !(O (F a))



bindF :: F a -> Box (a -> F b) -> F b
bindF (Now x) f = unbox f x
bindF (Wait x) f = Wait (delay (bindF (adv x) f))

mapF :: Box (a -> b) -> F a -> F b
mapF f d = d `bindF` (box (\ x -> Now (unbox f x)))


sync :: O (F a) -> O (F b) -> O (F a :* F b)
sync x y = delay (case select x y of
                     Fst x' y' -> (x' :* Wait y')
                     Snd x' y' -> (Wait x' :* y')
                     Both x' y' -> (x' :* y'))

syncF :: (Stable a, Stable b) => F a -> F b -> F (a :* b)
syncF (Now x) (Now y) = Now (x :* y)
syncF (Wait x) (Now y) = Wait (delay (syncA (adv x) y))
syncF (Now x) (Wait y) = Wait (delay (syncB x (adv y)))
syncF (Wait x) (Wait y) = Wait (delay (case select x y of
                                         Fst x' y' -> syncF x' (Wait y')
                                         Snd x' y' -> syncF (Wait x') y'
                                         Both x' y' -> syncF x' y'
                                      )) 

syncA :: (Stable b) => F a -> b -> F (a :* b)
syncA (Now x) y = Now (x :* y)
syncA (Wait x) y = Wait (delay (syncA (adv x) y))


syncB :: (Stable a) => a -> F b -> F (a :* b)
syncB x (Now y) = Now (x :* y)
syncB x (Wait y) = Wait (delay (syncB x (adv y)))


-- | @SigF a@ is a signal of values of type @a@. In contrast to 'Sig',
-- 'SigF' supports the 'filter' and 'filterMap' functions.
data SigF a = !a :>: !(O (F (SigF a)))


-- | Get the current value of a signal.
current :: SigF a -> a
current (x :>: _) = x


-- | Get the future the signal.
future :: SigF a -> O (F (SigF a))
future (_ :>: xs) = xs


mkSigF :: Box (O a) -> F (SigF a)
mkSigF b = Wait (mkSigF' b) where

mkSigF' :: Box (O a) -> O (F (SigF a))
mkSigF' b = delay (Now (adv (unbox b) :>: mkSigF' b))


fromSig :: Sig a -> SigF a
fromSig (x ::: xs) = x :>: delay (Now (fromSig (adv xs)))

  
switchAwait :: F (SigF a) -> F (SigF a) -> F(SigF a)
switchAwait _ (Now ys) = Now ys
switchAwait (Now (x :>: xs)) (Wait ys) = Now (x :>: delay (uncurry' switchAwait (adv (sync xs ys)) ))
switchAwait (Wait xs) (Wait ys) = Wait (delay (uncurry' switchAwait (adv (sync xs ys)) ))

switch :: SigF a -> F (SigF a) -> SigF a
switch _ (Now ys) = ys
switch (x :>: xs) (Wait ys) = x :>: delay (uncurry' switchAwait (adv (sync xs ys)))

switchS :: Stable a => SigF a -> F (a -> SigF a) -> SigF a
switchS (x :>: _) (Now f) = f x
switchS (x :>: xs) (Wait ys) = x :>: delay (uncurry' (switchAwaitS x) (adv (sync xs ys)))

switchAwaitS :: Stable a => a -> F (SigF a) -> F (a -> SigF a) -> F (SigF a)
switchAwaitS _ (Now (x :>: _)) (Now f) = Now (f x)
switchAwaitS _ (Now (x :>: xs)) (Wait ys) =
  Now (x :>: delay (uncurry' (switchAwaitS x) (adv (sync xs ys))))
switchAwaitS x (Wait _) (Now f) = Now (f x)
switchAwaitS x (Wait xs) (Wait ys) = Wait (delay (uncurry' (switchAwaitS x) (adv (sync xs ys))))



filterMapAwait :: Box (a -> Maybe' b) -> F(SigF a) -> F (SigF b)
filterMapAwait f (Wait xs) = Wait (delay (filterMapAwait f (adv xs)))
filterMapAwait f (Now (x :>: xs)) = case unbox f x of
                                     Just' y  -> Now (y :>: delay (filterMapAwait f (adv xs)))
                                     Nothing' -> Wait (delay (filterMapAwait f (adv xs)))

filterMap :: Box (a -> Maybe' b) -> SigF a -> F (SigF b)
filterMap f xs = filterMapAwait f (Now xs)


filterAwait :: Box (a -> Bool) -> F( SigF a) -> F (SigF a)
filterAwait p = filterMapAwait (box (\ x -> if unbox p x then Just' x else Nothing'))

filter :: Box (a -> Bool) -> SigF a -> F (SigF a)
filter p = filterMap (box (\ x -> if unbox p x then Just' x else Nothing'))

trigger :: Stable b => Box (a -> b -> c) -> SigF a -> SigF b -> SigF c
trigger f (a :>: as) (b :>: bs) =
  unbox f a b :>:
  delay (uncurry' (trigger' b f) (adv (sync as bs)))

triggerAwait :: Stable b => Box (a -> b -> c) -> F (SigF a) -> SigF b -> F (SigF c)
triggerAwait f (Now (a :>: as)) (b :>: bs)
  = Now (unbox f a b :>: delay (uncurry' (trigger' b f) (adv (sync as bs))))
triggerAwait f (Wait as) (b :>: bs)
  = Wait (delay (uncurry' (trigger' b f) (adv (sync as bs))))

trigger' :: Stable b => b -> Box (a -> b -> c) -> F (SigF a) -> F (SigF b) -> F (SigF c)
trigger' b f (Now (a :>: as)) (Wait bs) =
  Now (unbox f a b :>: delay (uncurry' (trigger' b f) (adv (sync as bs))))
trigger' _ f (Now (a :>: as)) (Now (b :>: bs)) =
  Now (unbox f a b :>: delay (uncurry' (trigger' b f) (adv (sync as bs))))
trigger' b f (Wait as) (Wait bs) =
  Wait (delay (uncurry' (trigger' b f) (adv (sync as bs))))
trigger' _ f (Wait as) (Now (b :>: bs)) =
  Wait (delay (uncurry' (trigger' b f) (adv (sync as bs))))


mapAwait :: Box (a -> b) -> F (SigF a) -> F (SigF b)
mapAwait f (Now (x :>: xs)) = Now (unbox f x :>: delay (mapAwait f (adv xs)))
mapAwait f (Wait xs) = Wait (delay (mapAwait f (adv xs)))

map :: Box (a -> b) -> SigF a -> SigF b
map f (x :>: xs) = unbox f x :>: delay (mapAwait f (adv xs))



zipWith :: (Stable a, Stable b) => Box(a -> b -> c) -> SigF a -> SigF b -> SigF c
zipWith f (a :>: as) (b :>: bs) = unbox f a b :>: delay (uncurry' (zipWithAwait f a b) (adv (sync as bs)))

zipWithAwait :: (Stable a, Stable b) => Box(a -> b -> c) -> a -> b -> F (SigF a) -> F (SigF b) -> F (SigF c)
zipWithAwait f _ _ (Now (a :>: as)) (Now (b :>: bs)) = Now (unbox f a b :>: delay (uncurry' (zipWithAwait f a b) (adv (sync as bs))))
zipWithAwait f _ b (Now (a :>: as)) (Wait bs) = Now (unbox f a b :>: delay (uncurry' (zipWithAwait f a b) (adv (sync as bs))))
zipWithAwait f a _ (Wait as) (Now (b :>: bs)) = Now (unbox f a b :>: delay (uncurry' (zipWithAwait f a b) (adv (sync as bs))))
zipWithAwait f a b (Wait as) (Wait bs) = Wait (delay (uncurry' (zipWithAwait f a b) (adv (sync as bs))))

scan :: (Stable b) => Box(b -> a -> b) -> b -> SigF a -> SigF b
scan f acc (a :>: as) = acc' :>: delay (scanAwait f acc' (adv as))
  where acc' = unbox f acc a

scanAwait :: (Stable b) => Box (b -> a -> b) -> b -> F (SigF a) -> F (SigF b)
scanAwait f acc (Now (a :>: as)) = Now (acc' :>: delay (scanAwait f acc' (adv as)))
  where acc' = unbox f acc a
scanAwait f acc (Wait as) = Wait (delay (scanAwait f acc (adv as)))