-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Arrowized functional state machines
--
-- Arrowized functional state machines. This module is inspired by Yampa
-- and the paper Functional Reactive Programming, Continued*
-- written by Henrik Nilsson, Antony Courtney and John Peterson.
@package AFSM
@version 0.1.3.1
module Data.SF.CoreType
data SF a b
SF :: (a -> (SF a b, b)) -> SF a b
module Data.SF.Core
instance Control.Category.Category Data.SF.CoreType.SF
instance Control.Arrow.Arrow Data.SF.CoreType.SF
instance Control.Arrow.ArrowChoice Data.SF.CoreType.SF
instance Control.Arrow.ArrowApply Data.SF.CoreType.SF
instance Control.Arrow.ArrowLoop Data.SF.CoreType.SF
-- | Stateful functions It is the same with SMH, and it just removes the
-- empty storage.
module Data.SF
data SF a b
SF :: (a -> (SF a b, b)) -> SF a b
module Control.AFSM.CoreType
-- | TF is a type representing a transition function. s: storage, a:
-- input, b: output Let's explain more about TF. When a state gets
-- an input a, it should do three things base on the storage and input:
-- find the next state, update storage and output b. That's why it looks
-- like this: (storage -> a -> (SM newState newStorage, b)) type TF
-- storage input output = (storage -> input -> (SM storage input
-- output, output)) Also, it is an instance of Arrow, it represents a
-- machine without initial storage. composing two TF represents that two
-- SM shares the same storage
newtype TF s a b
TF :: (s -> a -> (SM s a b, b)) -> TF s a b
-- | STF is the type of simple transition function.
type STF s a b = s -> a -> (s, b)
-- | SM is a type representing a state machine. (TF s a b): initial
-- state(transition function), s: initial storage SM storage input output
-- = SM (TF storage input output) storage
data SM s a b
SM :: (TF s a b) -> s -> SM s a b
tf :: SM s a b -> (s -> a -> (SM s a b, b))
st :: SM s a b -> s
-- | It is the same with the SM constructor.
newSM :: (s -> a -> (SM s a b, b)) -> s -> SM s a b
-- | build a simple SM which have only one TF.
simpleSM :: (s -> a -> (s, b)) -> s -> SM s a b
-- | SMH is the type of the state machine with hidden or no storage.
-- It is the same type with Circuit a b = Circuit (a -> Circuit a b,
-- b)
type SMH a b = SM () a b
-- | Event type, there are 4 different events: event a, no event,
-- error event string and exit event.
data Event a
Event :: a -> Event a
NoEvent :: Event a
ErrEvent :: String -> Event a
ExitEvent :: Event a
instance GHC.Classes.Ord a => GHC.Classes.Ord (Control.AFSM.CoreType.Event a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Control.AFSM.CoreType.Event a)
instance GHC.Show.Show a => GHC.Show.Show (Control.AFSM.CoreType.Event a)
instance GHC.Show.Show s => GHC.Show.Show (Control.AFSM.CoreType.SM s a b)
module Control.AFSM.Util
f1template :: (a1 -> a0) -> (a1 -> b0 -> b1) -> (s -> a0 -> (SM s a0 b0, b0)) -> s -> a1 -> (SM s a1 b1, b1)
f2template :: (a2 -> (a0, a1)) -> (a2 -> b0 -> b1 -> b2) -> (s0 -> a0 -> (SM s0 a0 b0, b0)) -> (s1 -> a1 -> (SM s1 a1 b1, b1)) -> (s0, s1) -> a2 -> (SM (s0, s1) a2 b2, b2)
absorb :: (a1 -> a0) -> (a1 -> b0 -> b1) -> SM s a0 b0 -> SM s a1 b1
merge :: (a2 -> (a0, a1)) -> (a2 -> b0 -> b1 -> b2) -> SM s0 a0 b0 -> SM s1 a1 b1 -> SM (s0, s1) a2 b2
module Control.AFSM.Core
-- | Source There are two kinds of source. First one is using the output of
-- `SM s a a` as its input, then it becomes a perpetual motion, :) Second
-- one is a SM which ignore its input, and output something based on its
-- storage. The second one is easier to understand and use.
--
-- build a source, for example: buildSrc $ foldlDelaySM (const (+1)) 0
-- [0..] buildSrc $ foldlDelaySM (+) 1 [1, 2, 4, 8, ...]
buildSrc :: SM s a a -> [a]
-- | build a simple source, which ignore the inputs fibsSM :: SM (Int, Int)
-- () Int fibsSM = simpleSM ((a, b) () -> ((b, a+b), a)) (0, 1) take
-- 10 $ simpleSrc fibsSM [0,1,1,2,3, ...]simpleSrc :: SM s () a -> [a]
simpleSrc :: SM s () a -> [a]
-- | build a SM which just output its input
idSM :: SM () a a
-- | build a SM which always return b
constSM :: b -> SM () a b
-- | delay the input with given value. delaySM = foldlDelaySM (const id)
delaySM :: a -> SM a a a
-- | build a SM from a function
arrSM :: (a -> b) -> SM () a b
-- | the same with foldl
foldlSM :: (s -> a -> s) -> s -> SM s a s
-- | the difference from foldlSM is it output the storage first.
foldlDelaySM :: (s -> a -> s) -> s -> SM s a s
-- | absorb a function. absorbR sm f = absorbRSM sm (arrSM f) absorbL f sm
-- = absorbLSM (arrSM f) sm
absorbR :: SM s a b -> (b -> c) -> SM s a c
absorbL :: (a -> b) -> SM s b c -> SM s a c
(^>>>) :: (a -> b) -> SM s b c -> SM s a c
infixr 1 ^>>>
(>>>^) :: SM s a b -> (b -> c) -> SM s a c
infixr 1 >>>^
(<<<^) :: SM s b c -> (a -> b) -> SM s a c
infixr 1 <<<^
(^<<<) :: (b -> c) -> SM s a b -> SM s a c
infixr 1 ^<<<
-- | compose two SM and merge their storage.
composeSM :: SM s1 b c -> SM s0 a b -> SM (s0, s1) a c
-- | Right-to-left composition
(<<<<) :: SM s1 b c -> SM s0 a b -> SM (s0, s1) a c
infixr 1 <<<<
-- | Left-to-right composition
(>>>>) :: SM s0 a b -> SM s1 b c -> SM (s0, s1) a c
infixr 1 >>>>
firstSM :: SM s a b -> SM s (a, c) (b, c)
secondSM :: SM s a b -> SM s (c, a) (c, b)
productSM :: SM s0 a b -> SM s1 c d -> SM (s0, s1) (a, c) (b, d)
fanoutSM :: SM s0 a b -> SM s1 a c -> SM (s0, s1) a (b, c)
(****) :: SM s0 a b -> SM s1 c d -> SM (s0, s1) (a, c) (b, d)
infixr 3 ****
(&&&&) :: SM s0 a b -> SM s1 a c -> SM (s0, s1) a (b, c)
infixr 3 &&&&
leftSM :: SM s a b -> SM s (Either a c) (Either b c)
rightSM :: SM s a b -> SM s (Either c a) (Either c b)
sumSM :: SM s0 a b -> SM s1 c d -> SM (s0, s1) (Either a c) (Either b d)
faninSM :: SM s0 a c -> SM s1 b c -> SM (s0, s1) (Either a b) c
(++++) :: SM s0 a b -> SM s1 c d -> SM (s0, s1) (Either a c) (Either b d)
infixr 2 ++++
(||||) :: SM s0 a c -> SM s1 b c -> SM (s0, s1) (Either a b) c
infixr 2 ||||
loopSM :: SM s (a, c) (b, c) -> SM s a b
-- | converts SM a b -> SM [a] [b], it is very useful to compose SM a
-- [b] and SM b c to SM a [c].
execSM :: SM s a b -> SM s [a] [b]
joinSM :: Monad m => SM s a (m (m b)) -> SM s a (m b)
concatSM :: SM s a [[b]] -> SM s a [b]
-- | run SM a b with a.
step :: SM s a b -> a -> (SM s a b, b)
-- | execute SM a b with input [a]. Also, it is the map function for SM,
-- perhaps, We should define our own Functor class, the SMFunctor!
exec :: SM s a b -> [a] -> (SM s a b, [b])
-- | fmapSM f sm = sm >>> arr f
fmapSM :: (b -> c) -> SM s a b -> SM s a c
instance GHC.Base.Functor (Control.AFSM.CoreType.SM s a)
module Control.AFSM.TF
-- | transform `SM t (s, a) (s, b)` to `TF s a b`
transSM2TF :: SM t (s, a) (s, b) -> TF s a b
idTF :: TF s a a
composeTF :: TF s b c -> TF s a b -> TF s a c
arrTF :: (a -> b) -> TF s a b
firstTF :: TF s a b -> TF s (a, c) (b, c)
leftTF :: TF s a b -> TF s (Either a c) (Either b c)
rightTF :: TF s a b -> TF s (Either c a) (Either c b)
sumTF :: TF s a b -> TF s c d -> TF s (Either a c) (Either b d)
faninTF :: TF s a c -> TF s b c -> TF s (Either a b) c
appTF :: TF s (TF s a b, a) b
loopTF :: TF s (a, c) (b, c) -> TF s a b
instance Control.Category.Category (Control.AFSM.CoreType.TF s)
instance Control.Arrow.Arrow (Control.AFSM.CoreType.TF s)
instance Control.Arrow.ArrowChoice (Control.AFSM.CoreType.TF s)
instance Control.Arrow.ArrowApply (Control.AFSM.CoreType.TF s)
instance Control.Arrow.ArrowLoop (Control.AFSM.CoreType.TF s)
module Control.AFSM.SMFunctor
class SMFunctor f where smfmap sm a = snd $ smexec sm a
smexec :: SMFunctor f => SM s a b -> f a -> (SM s a b, f b)
smfmap :: SMFunctor f => SM s a b -> f a -> f b
smexecSM :: SMFunctor f => SM s a b -> SM s (f a) (f b)
smexecSMA :: SMFunctor f => SM s a b -> SM (SM s a b) (f a) (f b)
bindSM :: (Monad m, SMFunctor m) => m a -> SM s a (m b) -> (SM s a (m b), m b)
(>>>=) :: (Monad m, SMFunctor m) => m a -> SM s a (m b) -> m b
instance Control.AFSM.SMFunctor.SMFunctor []
instance Control.AFSM.SMFunctor.SMFunctor GHC.Base.Maybe
instance Control.AFSM.SMFunctor.SMFunctor ((->) r)
instance Control.AFSM.SMFunctor.SMFunctor (Data.Either.Either a)
instance Control.AFSM.SMFunctor.SMFunctor ((,) a)
instance (Control.AFSM.SMFunctor.SMFunctor f, Control.AFSM.SMFunctor.SMFunctor g) => Control.AFSM.SMFunctor.SMFunctor (Data.Functor.Compose.Compose f g)
module Control.AFSM.Event
-- | Event type, there are 4 different events: event a, no event,
-- error event string and exit event. data Event a = Event a | NoEvent |
-- ErrEvent String | ExitEvent deriving (Show, Eq, Ord)
--
-- extract [a] from [Event a]
extractEvents :: [Event a] -> [a]
instance GHC.Base.Functor Control.AFSM.CoreType.Event
instance GHC.Base.Applicative Control.AFSM.CoreType.Event
instance GHC.Base.Monad Control.AFSM.CoreType.Event
instance Control.AFSM.SMFunctor.SMFunctor Control.AFSM.CoreType.Event
module Control.AFSM.SMH
-- | the same constructor with newSM
newSMH :: (() -> a -> (SMH a b, b)) -> SMH a b
-- | the same constructor with simpleSM
simpleSMH :: (s -> a -> (s, b)) -> s -> SMH a b
-- | hide the Storage type in the transition function.
hideStorage :: SM s a b -> SMH a b
instance Control.Category.Category (Control.AFSM.CoreType.SM ())
instance Control.Arrow.Arrow (Control.AFSM.CoreType.SM ())
instance Control.Arrow.ArrowChoice (Control.AFSM.CoreType.SM ())
instance Control.Arrow.ArrowApply (Control.AFSM.CoreType.SM ())
instance Control.Arrow.ArrowLoop (Control.AFSM.CoreType.SM ())
-- | Arrowized functional state machines.
--
-- This module is inspired by Yampa and the paper Functional Reactive
-- Programming, Continued* written by Henrik Nilsson, Antony Courtney
-- and John Peterson.
module Control.AFSM
-- | Event type, there are 4 different events: event a, no event,
-- error event string and exit event.
data Event a
Event :: a -> Event a
NoEvent :: Event a
ErrEvent :: String -> Event a
ExitEvent :: Event a
class SMFunctor f where smfmap sm a = snd $ smexec sm a
smexec :: SMFunctor f => SM s a b -> f a -> (SM s a b, f b)
smfmap :: SMFunctor f => SM s a b -> f a -> f b
-- | TF is a type representing a transition function. s: storage, a:
-- input, b: output Let's explain more about TF. When a state gets
-- an input a, it should do three things base on the storage and input:
-- find the next state, update storage and output b. That's why it looks
-- like this: (storage -> a -> (SM newState newStorage, b)) type TF
-- storage input output = (storage -> input -> (SM storage input
-- output, output)) Also, it is an instance of Arrow, it represents a
-- machine without initial storage. composing two TF represents that two
-- SM shares the same storage
newtype TF s a b
TF :: (s -> a -> (SM s a b, b)) -> TF s a b
-- | transform `SM t (s, a) (s, b)` to `TF s a b`
transSM2TF :: SM t (s, a) (s, b) -> TF s a b
-- | SM is a type representing a state machine. (TF s a b): initial
-- state(transition function), s: initial storage SM storage input output
-- = SM (TF storage input output) storage
data SM s a b
SM :: (TF s a b) -> s -> SM s a b
-- | It is the same with the SM constructor.
newSM :: (s -> a -> (SM s a b, b)) -> s -> SM s a b
-- | build a simple SM which have only one TF.
simpleSM :: (s -> a -> (s, b)) -> s -> SM s a b
tf :: SM s a b -> (s -> a -> (SM s a b, b))
st :: SM s a b -> s
-- | SMH is the type of the state machine with hidden or no storage.
-- It is the same type with Circuit a b = Circuit (a -> Circuit a b,
-- b)
type SMH a b = SM () a b
-- | the same constructor with newSM
newSMH :: (() -> a -> (SMH a b, b)) -> SMH a b
-- | the same constructor with simpleSM
simpleSMH :: (s -> a -> (s, b)) -> s -> SMH a b
-- | hide the Storage type in the transition function.
hideStorage :: SM s a b -> SMH a b
-- | Source There are two kinds of source. First one is using the output of
-- `SM s a a` as its input, then it becomes a perpetual motion, :) Second
-- one is a SM which ignore its input, and output something based on its
-- storage. The second one is easier to understand and use.
--
-- build a source, for example: buildSrc $ foldlDelaySM (const (+1)) 0
-- [0..] buildSrc $ foldlDelaySM (+) 1 [1, 2, 4, 8, ...]
buildSrc :: SM s a a -> [a]
-- | build a simple source, which ignore the inputs fibsSM :: SM (Int, Int)
-- () Int fibsSM = simpleSM ((a, b) () -> ((b, a+b), a)) (0, 1) take
-- 10 $ simpleSrc fibsSM [0,1,1,2,3, ...]simpleSrc :: SM s () a -> [a]
simpleSrc :: SM s () a -> [a]
-- | build a SM which always return b
constSM :: b -> SM () a b
-- | build a SM which just output its input
idSM :: SM () a a
-- | delay the input with given value. delaySM = foldlDelaySM (const id)
delaySM :: a -> SM a a a
-- | build a SM from a function
arrSM :: (a -> b) -> SM () a b
-- | the same with foldl
foldlSM :: (s -> a -> s) -> s -> SM s a s
-- | the difference from foldlSM is it output the storage first.
foldlDelaySM :: (s -> a -> s) -> s -> SM s a s
-- | compose two SM and merge their storage.
composeSM :: SM s1 b c -> SM s0 a b -> SM (s0, s1) a c
-- | Left-to-right composition
(>>>>) :: SM s0 a b -> SM s1 b c -> SM (s0, s1) a c
infixr 1 >>>>
-- | Right-to-left composition
(<<<<) :: SM s1 b c -> SM s0 a b -> SM (s0, s1) a c
infixr 1 <<<<
(^>>>) :: (a -> b) -> SM s b c -> SM s a c
infixr 1 ^>>>
(>>>^) :: SM s a b -> (b -> c) -> SM s a c
infixr 1 >>>^
(^<<<) :: (b -> c) -> SM s a b -> SM s a c
infixr 1 ^<<<
(<<<^) :: SM s b c -> (a -> b) -> SM s a c
infixr 1 <<<^
firstSM :: SM s a b -> SM s (a, c) (b, c)
secondSM :: SM s a b -> SM s (c, a) (c, b)
(****) :: SM s0 a b -> SM s1 c d -> SM (s0, s1) (a, c) (b, d)
infixr 3 ****
(&&&&) :: SM s0 a b -> SM s1 a c -> SM (s0, s1) a (b, c)
infixr 3 &&&&
leftSM :: SM s a b -> SM s (Either a c) (Either b c)
rightSM :: SM s a b -> SM s (Either c a) (Either c b)
(++++) :: SM s0 a b -> SM s1 c d -> SM (s0, s1) (Either a c) (Either b d)
infixr 2 ++++
(||||) :: SM s0 a c -> SM s1 b c -> SM (s0, s1) (Either a b) c
infixr 2 ||||
loopSM :: SM s (a, c) (b, c) -> SM s a b
absorb :: (a1 -> a0) -> (a1 -> b0 -> b1) -> SM s a0 b0 -> SM s a1 b1
merge :: (a2 -> (a0, a1)) -> (a2 -> b0 -> b1 -> b2) -> SM s0 a0 b0 -> SM s1 a1 b1 -> SM (s0, s1) a2 b2
-- | converts SM a b -> SM [a] [b], it is very useful to compose SM a
-- [b] and SM b c to SM a [c].
execSM :: SM s a b -> SM s [a] [b]
concatSM :: SM s a [[b]] -> SM s a [b]
-- | run SM a b with a.
step :: SM s a b -> a -> (SM s a b, b)
-- | execute SM a b with input [a]. Also, it is the map function for SM,
-- perhaps, We should define our own Functor class, the SMFunctor!
exec :: SM s a b -> [a] -> (SM s a b, [b])