on master help sign in
Fix Automaton library to match PLDI paper.
a66a4b1evancz
libraries/Automaton.elm+38−32
@@ -4,54 +4,60 @@
4-- it can be used.
4-- it can be used.
5module Automaton where
5module Automaton where
6
6
7−data Automaton a b = Automaton (a -> (b, Automaton a b))
7+data Automaton a b = Step (a -> (Automaton a b, b))
8
8
9−-- Run an automaton on a given signal. The automaton takes in ‘a’ values and returns ‘b’ values. The automaton steps forward whenever the input signal updates.
9+-- Run an automaton on a given signal. The automaton steps forward
10+-- whenever the input signal updates.
10−run : Automaton a b -> Signal a -> Signal b
11+run : Automaton a b -> b -> Signal a -> Signal b
11−run (Automaton m0) input =
12+run (Step f) base inputs =
12− lift fst $ foldp' (\a (b, Automaton m) -> m a) m0 input
13+ let step a (Step f, _) = f a
14+ in lift snd $ foldp step base inputs
13
15
14-- Step an automaton forward once with a given input.
16-- Step an automaton forward once with a given input.
15−step : Automaton a b -> a -> (b, Automaton a b)
17+step : a -> Automaton a b -> (Automaton a b, b)
16−step (Automaton m) a = m a
18+step a (Step f) = f a
17−
18
19
19-- Compose two automatons, chaining them together.
20-- Compose two automatons, chaining them together.
20(>>>) : Automaton a b -> Automaton b c -> Automaton a c
21(>>>) : Automaton a b -> Automaton b c -> Automaton a c
21−a1 >>> a2 =
22+f >>> g =
22− let Automaton m1 = a1
23+ Step (\a -> let (f', b) = step a f
23− Automaton m2 = a2
24+ (g', c) = step b g
24− in Automaton (\a -> let (b,m1') = m1 a
25+ in (f' >>> g', c))
25− (c,m2') = m2 b
26− in (c, m1' >>> m2'))
27
26
28-- Compose two automatons, chaining them together.
27-- Compose two automatons, chaining them together.
29(<<<) : Automaton b c -> Automaton a b -> Automaton a c
28(<<<) : Automaton b c -> Automaton a b -> Automaton a c
30−a2 <<< a1 = a1 >>> a2
29+g <<< f = f >>> g
31
30
32-- Combine a list of automatons into a single automaton that produces a list.
31-- Combine a list of automatons into a single automaton that produces a list.
33combine : [Automaton a b] -> Automaton a [b]
32combine : [Automaton a b] -> Automaton a [b]
34combine autos =
33combine autos =
35− Automaton (\a -> let (bs,autos') = unzip $ map (\(Automaton m) -> m a) autos in
34+ Step (\a -> let (autos', bs) = unzip $ map (step a) autos
36− (bs, combine autos'))
35+ in (combine autos', bs))
37−
36+
38−-- Create an automaton with no memory. It just applies the given function to every input.
37+-- Create an automaton with no memory. It just applies the given function to
38+-- every input.
39−pure : (a -> b) -> Automaton a b
39+pure : (a -> b) -> Automaton a b
40−pure f = Automaton (\x -> (f x, pure f))
40+pure f = Step (\x -> (pure f, f x))
41−
41+
42−-- Create an automaton with no memory. It just applies the given function to every input.
42+-- Create an automaton with state. Requires an initial state and a step
43+-- function to step the state forward.
43−init : b -> (a -> b -> b) -> Automaton a b
44+init : b -> (a -> b -> b) -> Automaton a b
44−init s step = Automaton (\a -> let s' = step a s in (s', init s' step))
45+init s f = Step (\x -> let s' = f x s
45−
46+ in (init s' f, s'))
47+
46−-- Create an automaton with hidden state. Requires an initial state and a step function to step the state forward and produce an output.
48+-- Create an automaton with hidden state. Requires an initial state and a
49+-- step function to step the state forward and produce an output.
47−init' : s -> (a -> s -> (b,s)) -> Automaton a b
50+init' : s -> (a -> s -> (s,b)) -> Automaton a b
48−init' s step = Automaton (\a -> let (b,s') = step a s in (b , init' s' step))
51+init' s f = Step (\x -> let (s',out) = f x s
52+ in (init' s' f, out))
49
53
50-- Count the number of steps taken.
54-- Count the number of steps taken.
51count : Automaton a Int
55count : Automaton a Int
52count = init 0 (\_ c -> c + 1)
56count = init 0 (\_ c -> c + 1)
53
57
54
58
59+{-- TODO(evancz): move this code to the Form library so people can find it.
60+
55data DragState = Listen | Ignore | DragFrom (Int,Int)
61data DragState = Listen | Ignore | DragFrom (Int,Int)
56
62
57vecSub (x1,y1) (x2,y2) = (x1-x2,y1-y2)
63vecSub (x1,y1) (x2,y2) = (x1-x2,y1-y2)
@@ -71,15 +77,15 @@ stepDrag (press,pos) (ds,form) =
71-- Create a draggable form that can be dynamically created and added to a scene.
77-- Create a draggable form that can be dynamically created and added to a scene.
72draggable : Form -> Automaton (Bool,(Int,Int)) Form
78draggable : Form -> Automaton (Bool,(Int,Int)) Form
73draggable form = init' (Listen,form) stepDrag
79draggable form = init' (Listen,form) stepDrag
80+--}
74
81
75−
76−{--- See the following papers for ideas on how to make this faster:
82+{-- TODO(evancz): See the following papers for ideas on how to make this
83+library faster and better:
77
84
78- Functional Reactive Programming, Continued
85- Functional Reactive Programming, Continued
79- Causal commutative arrows and their optimization
86- Causal commutative arrows and their optimization
80
87
81Speeding things up is a really low priority. Language features and
88Speeding things up is a really low priority. Language features and
82libraries with nice APIs and are way more important!
89libraries with nice APIs and are way more important!
83−
84--}
90--}
85
91