Netwire
From HaskellWiki
(→Running wires) |
(Writing wires) |
||
| Line 4: | Line 4: | ||
This wiki page corresponds to Netwire version 3 and is currently a work in progress. | This wiki page corresponds to Netwire version 3 and is currently a work in progress. | ||
| + | |||
== Features == | == Features == | ||
| Line 16: | Line 17: | ||
* signal analysis wires (average, peak, etc.), | * signal analysis wires (average, peak, etc.), | ||
* effectful wires. | * effectful wires. | ||
| + | |||
== Basics == | == Basics == | ||
| Line 52: | Line 54: | ||
type MyWire = Wire () (Kleisli IO) | type MyWire = Wire () (Kleisli IO) | ||
</haskell> | </haskell> | ||
| + | |||
== Running wires == | == Running wires == | ||
| Line 109: | Line 112: | ||
main :: IO () | main :: IO () | ||
main = testWireM 1000 (return 15) system | main = testWireM 1000 (return 15) system | ||
| + | </haskell> | ||
| + | |||
| + | |||
| + | == Predefined wires == | ||
| + | |||
| + | There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning): | ||
| + | |||
| + | <haskell> | ||
| + | constant :: b -> Wire e (>~) a b | ||
| + | identity :: Wire e (>~) b b | ||
| + | countFrom :: Enum b => b -> Wire e (>~) a b | ||
| + | </haskell> | ||
| + | |||
| + | The ''constant'' function takes an output value and produces a wire which produces that value constantly. So the wire <hask>constant 15</hask> will output 15 constantly at every instant. In other words, <hask>stepWireM</hask> will return <hask>Right 15</hask> along with a new wire that outputs 15 again: | ||
| + | |||
| + | <haskell> | ||
| + | stepWireM (constant 15) inp | ||
| + | -> (Right 15, constant 15) | ||
| + | </haskell> | ||
| + | |||
| + | Note the fully polymorphic input type <hask>a</hask>. This basically means that the wire disregards its input, so whatever <hask>inp</hask> is, it is ignored. | ||
| + | |||
| + | The ''identity'' wire is slightly more interesting. It has input and output of type <hask>b</hask>. What it does is: It simply outputs its input value at every instant: | ||
| + | |||
| + | <haskell> | ||
| + | stepWireM identity inp | ||
| + | -> (Right inp, identity) | ||
</haskell> | </haskell> | ||
[[Category:FRP]] | [[Category:FRP]] | ||
Revision as of 16:48, 1 December 2011
Netwire is a library for functional reactive programming, which uses the concept of arrows for modelling an embedded domain-specific language. This language lets you express reactive systems, which means systems that change over time. It shares the basic concept with Yampa and its fork Animas, but it is itself not a fork and has many additional features.
This wiki page corresponds to Netwire version 3 and is currently a work in progress.
Contents |
1 Features
Here is a list of some of the features of Netwire:
- arrow interface (or optionally an applicative interface),
- signal inhibition (ArrowZero / Alternative),
- signal selection (ArrowPlus / Alternative),
- self-adjusting wires (ArrowChoice),
- rich set of event wires,
- signal analysis wires (average, peak, etc.),
- effectful wires.
2 Basics
The Netwire library is based around a data type calledimport Control.Wire data Wire e (>~) a b
comp :: Wire e (>~) a b
a >~ Either e b
2.1 The inhibition monoid
The2.2 Base arrows
Thetype MyWire = Wire () (Kleisli IO)
3 Running wires
For running a wire you can use the stepping functions available in thestepWireM :: Monad m => Wire e (Kleisli m) a b -> a -> m (Either e b, Wire e (Kleisli m) a b)
stepWireM :: MyWire a b -> a -> IO (Either () b, MyWire a b)
system :: MyWire Int String system = {- ... -} main :: IO () main = loop system where loop :: MyWire Int String -> IO () loop w' = do (mx, w) <- stepWireM w' 15 {- ... do something with mx ... -} loop w -- loop with the new wire.
Note: Even though the FRP idea suggests it, there is no reason to run wires continuously or even regularly. You can totally have an instant depending on user input, a GUI event or network traffic, so instants can be minutes apart.
3.1 Testing wires
There is a convenient function for testing wires, which does all the plumbing for you. It's calledtestWireM :: (Show e, MonadIO m) => Int -> m a -> Wire e (Kleisli m) a String -> m ()
main :: IO () main = testWireM 1000 (return 15) system
4 Predefined wires
There are numerous predefined wires, which you can compose using the arrow interface. We will practice that with three very simple predefined wires (the type signatures are simplified for the sake of learning):
constant :: b -> Wire e (>~) a b identity :: Wire e (>~) b b countFrom :: Enum b => b -> Wire e (>~) a b
stepWireM (constant 15) inp -> (Right 15, constant 15)
stepWireM identity inp -> (Right inp, identity)
