public
Last active

Testing Yampa with simple examples.

  • Download Gist
feedback.hs
Haskell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
import FRP.Yampa
 
-- A feedback loop of the standard form from the link below.
system = feedback (-) (gain 5) (gain 0.1) 0
 
-- Construct a feedback loop with forward function 'a', reverse function 'b',
-- combine with 'f', and initial feedback value 'b0'.
-- http://upload.wikimedia.org/wikipedia/commons/e/ed/Ideal_feedback_model.svg
feedback :: (a -> a -> a) -> SF a a -> SF a a -> a -> SF a a
feedback f a b b0 = loopPre b0 inner
where
-- The inner function has two inputs and two outputs. Passing it to
-- 'loopPre' produces a function with one input and one output, because
-- inner's second output is connected to its second input.
inner = unsplit >>> a >>> identity &&& b
-- Combine elements of a tuple using 'f'.
unsplit = arr $ \t -> fst t `f` snd t
 
main = print $ embed fn signal
where fn = system
signal = deltaEncode dt [start .. end]
dt = 0.1
start = 1
end = 10
 
gain x = arr (*x)
simple.hs
Haskell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
import FRP.Yampa
 
-- Read 'SF' as 'signal function'. An 'SF Int Int' is therefore a signal with an
-- Int input and an Int output. This line just declares a type and is optional.
-- Haskell can normally deduce types automatically.
system :: SF Int Int
 
-- Our system is a composition of two other stream functions glued together
-- output-to-input.
system = gain 3 >>> offset 1
 
-- These functions construct signal functions from an int.
gain, offset :: Int -> SF Int Int
 
-- 'arr' turns regular functions into 'arrows', an abstraction which Yampa uses
-- to compose signal functions.
gain x = arr (*x)
offset x = arr (+x)
 
-- Run a signal through the system.
main = print $ embed fn signal
where fn = system
signal = deltaEncode dt [0 .. end]
dt = 0.1
end = 10
spring.hs
Haskell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
import FRP.Yampa
import Graphics.Gnuplot.Simple
 
system = force >>> displacement
 
force = constant (m * g)
 
displacement = feedback (-) (velocity >>> integrate) (gain $ k / m) 0
velocity = feedback (-) (integrate) (gain $ c / m) 0
 
m, g, k, c :: Double
m = 1
g = 9.81
k = 10
c = 1
 
main = plotPath [] (embed fn signal) where
-- 'time' again integrates the timestep to provide a definite output time
-- at each step, which we pass through to the output for plotting.
fn = time >>> pass &&& system
steps = 50
dt = 0.1
signal = deltaEncode dt $ replicate steps 0
 
integrate = imIntegral 0
 
pass = identity
 
gain x = arr (*x)
 
feedback op a b b0 = loopPre b0 inner
where inner = arr (uncurry op) >>> a >>> (identity &&& b)
time.hs
Haskell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import FRP.Yampa
import Text.Printf
 
-- 'time' outputs a constantly-increasing value representing the accumulated
-- time. The 'dt' value in the main function determines the timestep, encoded
-- into the signal and ignored in the previous examples. Here we make a
-- contrived example that generates values of sin(t).
system :: SF Time Double
system = time >>> arr sin
 
-- Use pretty printing!
main = mapM_ (printf "%.3f\n") $ embed fn signal
where fn = system
steps = 4
dt = pi / steps
signal = deltaEncode dt [0 .. steps]

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.