signals-0.0.0.1: Frontend/Signal.hs
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Frontend.Signal where
import Interpretation
import Frontend.Stream (Stream, Str)
import qualified Frontend.Stream as S
import Data.Dynamic
import Data.Typeable
import Prelude ( ($), (.), id
, Num, (+), (-), (*), fromInteger
, Fractional, (/), fromRational
, Floating, (**), pi, sin
, Eq, Show, String)
import qualified Prelude as P
--------------------------------------------------------------------------------
-- *
--------------------------------------------------------------------------------
-- | ...
data Signal exp a
where
-- ^ lifts consant streams into signals
Const :: Typeable a => Stream exp (exp a) -> Signal exp (Empty (exp a))
-- ^ lifts stream transformers into signal transformers, possibly state-full
Lift :: (Typeable a, Typeable b)
=> (Stream exp (exp a) -> Stream exp (exp b))
-> (Signal exp (Empty (exp a)) -> Signal exp (Empty (exp b)))
-- ^ maps a function over nested tuples to a function over signals
Map :: ( Typeable a, Typeable b
, StructT a, StructT b
, DomainT a ~ exp
, DomainT b ~ DomainT a)
=> (Struct exp a -> Struct exp b) -> Signal exp a -> Signal exp b
-- ^ joins together two nodes
Zip :: ( Typeable a, Typeable b
, StructT a, StructT b
, DomainT a ~ exp
, DomainT b ~ DomainT a)
=> Signal exp a -> Signal exp b -> Signal exp (a, b)
-- ^ breaks apart a signal of pairs, returning the first
Fst :: ( Typeable a, Typeable b
, StructT a, StructT b
, DomainT a ~ exp
, DomainT b ~ DomainT a)
=> Signal exp (a, b) -> Signal exp a
-- ^ breaks apart a signal of pairs, returning the second
Snd :: ( Typeable a, Typeable b
, StructT a, StructT b
, DomainT a ~ exp
, DomainT b ~ DomainT a)
=> Signal exp (a, b) -> Signal exp b
-- ^ prepends a value to the input signal
Delay :: Typeable a
=> exp a -> Signal exp (Empty (exp a)) -> Signal exp (Empty (exp a))
-- ^ dummy argument used in observable sharing
SVar :: (Typeable a, StructT a, DomainT a ~ exp)
=> Dynamic -> Signal exp a
deriving (Typeable)
-- | Signals with values ranging over the expression language
newtype Sig exp a = Sig {unSig :: Signal exp (Empty (exp a))}
--------------------------------------------------------------------------------
-- ** Instances
instance (Typeable exp, Typeable a, Num (exp a), Eq (exp a), Show a) => Num (Sig exp a)
where
fromInteger = repeat . fromInteger
(+) = zipWith (+)
(*) = zipWith (*)
(-) = zipWith (-)
abs = todo; signum = todo;
instance (Typeable exp, Typeable a, Fractional (exp a), Eq (exp a), Show a) => Fractional (Sig exp a)
where
fromRational = repeat . fromRational
(/) = zipWith (/)
recip = todo;
instance (Typeable exp, Typeable a, Floating (exp a), Eq (exp a), Show a) => Floating (Sig exp a)
where
pi = repeat pi
sin = map sin
(**) = zipWith (**)
exp = todo; sqrt = todo; log = todo;
tan = todo; cos = todo; asin = todo;
atan = todo; acos = todo; sinh = todo;
tanh = todo; cosh = todo; asinh = todo;
atanh = todo; acosh = todo; logBase = todo;
todo = P.error "unsupported operation"
--------------------------------------------------------------------------------
-- ** "Smart" constructors
constS :: (Typeable a) => Str exp a -> Sig exp a
constS = Sig . Const
liftS :: (Typeable a, Typeable b)
=> (Str exp a -> Str exp b) -> Sig exp a -> Sig exp b
liftS f = Sig . Lift f . unSig
mapS :: ( Typeable a, Typeable b
, StructT a, StructT b
, DomainT a ~ exp
, DomainT b ~ DomainT a)
=> (Struct exp a -> Struct exp b) -> Signal exp a -> Signal exp b
mapS = Map
--------------------------------------------------------------------------------
-- ** User Interface
repeat :: (Typeable a) => exp a -> Sig exp a
repeat = constS . S.repeat
map :: (Typeable a, Typeable b) => (exp a -> exp b) -> Sig exp a -> Sig exp b
map f = liftS $ S.map f
delay :: (Typeable a) => exp a -> Sig exp a -> Sig exp a
delay e = Sig . Delay e . unSig
zipWith :: (Typeable exp, Typeable a, Typeable b, Typeable c)
=> (exp a -> exp b -> exp c)
-> Sig exp a -> Sig exp b -> Sig exp c
zipWith f = P.curry $ lift $ P.uncurry f
--------------------------------------------------------------------------------
-- * Generalised lifting of Signals
--------------------------------------------------------------------------------
-- | 0-tuple value
data Empty a deriving Typeable
-- | Representation of nested tuples as a binary tree
data Struct exp a
where
Leaf :: Typeable a => exp a -> Struct exp (Empty (exp a))
Pair :: Struct exp a -> Struct exp b -> Struct exp (a, b)
deriving
Typeable
-- | Similar to `Struct`, with id's at the leafs
data TStruct exp a
where
TLeaf :: Typeable a => String -> TStruct exp (Empty (exp a))
TPair :: TStruct exp a -> TStruct exp b -> TStruct exp (a, b)
deriving
Typeable
--------------------------------------------------------------------------------
tpair :: TStruct exp a -> TStruct exp b -> TStruct exp (a, b)
tpair l r = TPair l r
tleaf :: Typeable a => String -> TStruct exp (Empty (exp a))
tleaf s = TLeaf s
tleft :: TStruct exp (a, b) -> TStruct exp a
tleft ~t = case t of (TPair l _) -> l
tright :: TStruct exp (a, b) -> TStruct exp b
tright ~t = case t of (TPair _ r) -> r
tid :: TStruct exp (Empty (exp a)) -> String
tid ~t = case t of (TLeaf i) -> i
--------------------------------------------------------------------------------
-- ** Conversion between signals and tuples
-- | ...
class StructS a
where
type Internal a :: *
type Domain a :: * -> *
fromS :: a -> Signal (Domain a) (Internal a)
toS :: Signal (Domain a) (Internal a) -> a
instance StructS (Signal exp (Empty (exp a)))
where
type Internal (Signal exp (Empty (exp a))) = Empty (exp a)
type Domain (Signal exp (Empty (exp a))) = exp
fromS = id
toS = id
instance StructS (Sig exp a)
where
type Internal (Sig exp a) = Empty (exp a)
type Domain (Sig exp a) = exp
fromS = unSig
toS = Sig
instance ( StructS a, StructT (Internal a), Typeable (Internal a)
, StructS b, StructT (Internal b), Typeable (Internal b)
, Domain a ~ Domain b
, DomainT (Internal a) ~ DomainT (Internal b)
, DomainT (Internal a) ~ Domain a
) =>
StructS (a, b)
where
type Internal (a, b) = (Internal a, Internal b)
type Domain (a, b) = Domain a
fromS (a, b) = Zip (fromS a) (fromS b)
toS p = (toS (Fst p), toS (Snd p))
--------------------------------------------------------------------------------
-- ** Conversion between signals and empty structs (used to remove structs later on)
class StructT a
where
type DomainT a :: * -> *
rep :: c (DomainT a) a -> TStruct (DomainT a) a
instance Typeable a => StructT (Empty (exp a))
where
type DomainT (Empty (exp a)) = exp
rep _ = TLeaf ""
instance ( StructT a, Typeable a
, StructT b, Typeable b
, DomainT a ~ DomainT b) =>
StructT (a, b)
where
type DomainT (a, b) = DomainT a
rep p = TPair (rep $ left p) (rep $ right p)
where
left :: c (DomainT a) (a, b) -> c (DomainT a) a
left = P.undefined
right :: c (DomainT b) (a, b) -> c (DomainT b) b
right = P.undefined
--------------------------------------------------------------------------------
-- ** Conversion between struct's and tuples
-- | ...
class StructE a
where
type Normal a :: *
type DomainE a :: * -> *
fromE :: Struct (DomainE a) a -> Normal a
toE :: Normal a -> Struct (DomainE a) a
instance Typeable a => StructE (Empty (exp a))
where
type Normal (Empty (exp a)) = exp a
type DomainE (Empty (exp a)) = exp
fromE (Leaf a) = a
toE a = Leaf a
instance ( StructE a
, StructE b
, DomainE a ~ DomainE b
) =>
StructE (a, b)
where
type Normal (a, b) = (Normal a, Normal b)
type DomainE (a, b) = DomainE a
fromE (Pair a b) = (fromE a, fromE b)
toE (a, b) = Pair (toE a) (toE b)
--------------------------------------------------------------------------------
-- ** Lifting operator
-- | ...
lift
:: ( -- ...
StructT (Internal s1) , StructT (Internal s2)
, DomainT (Internal s1) ~ Domain s2
, DomainT (Internal s2) ~ Domain s2
-- we must be able to do the signal \ tuple transformations
, StructS s1 , StructS s2
, StructE (Internal s1), StructE (Internal s2)
-- the `exp` type of the signals and tuples should be the same
, Domain s1 ~ Domain s2
, DomainE (Internal s1) ~ Domain s1
, DomainE (Internal s2) ~ Domain s2
-- requires typeable since we make use of `Zip` to transform signals
, Typeable (Internal s1), Typeable (Internal s2)
)
=> (Normal (Internal s1) -> Normal (Internal s2)) -> s1 -> s2
lift f = toS . mapS (toE . f . fromE) . fromS