{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
{-# OPTIONS_HADDOCK hide, prune #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  ForSyDe.Atom.MoC.SY.Core
-- Copyright   :  (c) George Ungureanu, KTH/ICT/E 2015-2016
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  ugeorge@kth.se
-- Stability   :  experimental
-- Portability :  portable
--
-- This module implements the core semantics of the SY atoms
-- 
-----------------------------------------------------------------------------

module ForSyDe.Atom.MoC.SY.Core where

import ForSyDe.Atom.MoC
import ForSyDe.Atom.MoC.Stream
import ForSyDe.Atom.Utility.Tuple

-- | Type synonym for a SY signal, i.e. "an ordered stream of SY
-- events"
type Signal a   = Stream (SY a)

-- | The SY event. It defines a synchronous signal.
newtype SY a  = SY { SY a -> a
val :: a -- ^ value wrapped by the 'SY' event
                              -- constructor.
                   }
  
-- | Implenents the execution semantics for the SY MoC atoms.
instance MoC SY where
  type Fun SY a b = a -> b
  type Ret SY b   = b 
  ---------------------
  -.- :: Fun SY a b -> Stream (SY a) -> Stream (SY b)
(-.-) = (SY a -> SY b) -> Stream (SY a) -> Stream (SY b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((SY a -> SY b) -> Stream (SY a) -> Stream (SY b))
-> ((a -> b) -> SY a -> SY b)
-> (a -> b)
-> Stream (SY a)
-> Stream (SY b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> SY a -> SY b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
  ---------------------
  -*- :: Stream (SY (Fun SY a b)) -> Stream (SY a) -> Stream (SY b)
(-*-) a :: Stream (SY (Fun SY a b))
a = Stream (SY a -> SY b) -> Stream (SY a) -> Stream (SY b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>) ((SY (a -> b) -> SY a -> SY b)
-> Stream (SY (a -> b)) -> Stream (SY a -> SY b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SY (a -> b) -> SY a -> SY b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>) Stream (SY (Fun SY a b))
Stream (SY (a -> b))
a)
  -* :: Stream (SY (Ret SY b)) -> Stream (SY b)
(-*) = Stream (SY (Ret SY b)) -> Stream (SY b)
forall a. a -> a
id
  ---------------------
  -<- :: Stream (SY a) -> Stream (SY a) -> Stream (SY a)
(-<-) (a :: SY a
a:-_) = SY a -> Stream (SY a) -> Stream (SY a)
forall e. e -> Stream e -> Stream e
(:-) SY a
a
  ---------------------
  -&- :: Stream (SY a) -> Stream (SY a) -> Stream (SY a)
(-&-) _ a :: Stream (SY a)
a = Stream (SY a)
a
  ---------------------

-- | Shows the value wrapped
instance Show a => Show (SY a) where
  showsPrec :: Int -> SY a -> ShowS
showsPrec _ (SY x :: a
x) = String -> ShowS
forall a. [a] -> [a] -> [a]
(++) (a -> String
forall a. Show a => a -> String
show a
x)

-- | Reads the value wrapped
instance Read a => Read (SY a) where
  readsPrec :: Int -> ReadS (SY a)
readsPrec _ s :: String
s = [(a -> SY a
forall a. a -> SY a
SY a
x, String
r) | (x :: a
x, r :: String
r) <- ReadS a
forall a. Read a => ReadS a
reads String
s]

-- | Allows for mapping of functions on a SY event.
instance Functor (SY) where
  fmap :: (a -> b) -> SY a -> SY b
fmap f :: a -> b
f (SY a :: a
a) = b -> SY b
forall a. a -> SY a
SY (a -> b
f a
a)

-- | Allows for lifting functions on a pair of SY events.
instance Applicative (SY) where
  pure :: a -> SY a
pure = a -> SY a
forall a. a -> SY a
SY 
  (SY a :: a -> b
a) <*> :: SY (a -> b) -> SY a -> SY b
<*> (SY b :: a
b) = b -> SY b
forall a. a -> SY a
SY (a -> b
a a
b)

-----------------------------------------------------------------------------

unit  :: a -> Signal a
unit :: a -> Signal a
unit  = SY a -> Signal a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SY a -> Signal a) -> (a -> SY a) -> a -> Signal a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> SY a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
-- | Wraps a (tuple of) value(s) into the equivalent unit signal(s). A
-- unit signal is a signal with one event, i.e. a singleton.
--
-- Provided helpers: @unit@, @unit2@, @unit3@, @unit4@.
unit2 :: (a, a) -> (Signal a, Signal a)
unit2 = (a -> Signal a, a -> Signal a) -> (a, a) -> (Signal a, Signal a)
forall a1 b1 a2 b2. (a1 -> b1, a2 -> b2) -> (a1, a2) -> (b1, b2)
($$) (a -> Signal a
forall a. a -> Signal a
unit, a -> Signal a
forall a. a -> Signal a
unit)
unit3 :: (a, a, a) -> (Signal a, Signal a, Signal a)
unit3 = (a -> Signal a, a -> Signal a, a -> Signal a)
-> (a, a, a) -> (Signal a, Signal a, Signal a)
forall t1 a t2 b t3 c.
(t1 -> a, t2 -> b, t3 -> c) -> (t1, t2, t3) -> (a, b, c)
($$$) (a -> Signal a
forall a. a -> Signal a
unit, a -> Signal a
forall a. a -> Signal a
unit, a -> Signal a
forall a. a -> Signal a
unit)
unit4 :: (a, a, a, a) -> (Signal a, Signal a, Signal a, Signal a)
unit4 = (a -> Signal a, a -> Signal a, a -> Signal a, a -> Signal a)
-> (a, a, a, a) -> (Signal a, Signal a, Signal a, Signal a)
forall t1 a t2 b t3 c t4 d.
(t1 -> a, t2 -> b, t3 -> c, t4 -> d)
-> (t1, t2, t3, t4) -> (a, b, c, d)
($$$$) (a -> Signal a
forall a. a -> Signal a
unit, a -> Signal a
forall a. a -> Signal a
unit, a -> Signal a
forall a. a -> Signal a
unit, a -> Signal a
forall a. a -> Signal a
unit)

-- | Transforms a list of values into a SY signal.
signal   :: [a] -> Signal a
signal :: [a] -> Signal a
signal l :: [a]
l = [SY a] -> Signal a
forall a. [a] -> Stream a
stream (a -> SY a
forall a. a -> SY a
SY (a -> SY a) -> [a] -> [SY a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a]
l)

-- | Reads a signal from a string. Like with the 'Prelude.read' function from
-- @Prelude@, you must specify the type of the signal.
--
-- >>> readSignal "{1,2,3,4,5}" :: Signal Int
-- {1,2,3,4,5}
readSignal :: Read a => String -> Signal a
readSignal :: String -> Signal a
readSignal = String -> Signal a
forall a. Read a => String -> a
read