Yampa
Yampa copied to clipboard
Functional Reactive Programming domain-specific language for efficient hybrid systems
Yampa
Domain-specific language embedded in Haskell for programming hybrid (mixed discrete-time and continuous-time) systems. Yampa is based on the concepts of Functional Reactive Programming (FRP).
Installation • Examples • Related projects • Documentation • Contributions • History
Features
-
Implements Functional Reactive Programming.
-
Allows for dynamic programs whose structure changes over time.
-
Isolates of effect-free signal functions from effectful actions.
-
Runs fast and is memory efficient.
-
Has been industry tested.
-
Provides a robust, elegant, stable interface.
-
Has well-defined semantics.
-
Supports applicative, functional and arrowized styles.
-
Supports all platforms and enjoys multiple backends.
-
Programs can be tested with QuickCheck and debugged using Haskell Titan.
Table of Contents
-
Installation
- Pre-requisites
- Compilation
- Examples
-
Related projects
- Games and applications
- Use in industry
- Backends
- Testing
- Other projects
-
Documentation
- API documentation and tutorials
- Publications
-
Contributions
- Structure and internals
- Style
- Version control
- Versioning model
- History
Installation
(Back to top)
Pre-requisites
(Back to top)
To use Yampa, you must have a Haskell compiler installed (GHC). We currently support all versions of GHC from 7.6.3 to modern versions (9.X series as of this writing).
On Debian/Ubuntu, the Haskell toolchain can be installed with:
$ apt-get install ghc cabal-install
On Mac, they can be installed with:
$ brew install ghc cabal-install
Compilation
(Back to top)
Once you have a working set of Haskell tools installed, install Yampa from hackage by executing:
$ cabal update
$ cabal install --lib Yampa
Running the following will print the word Success
if installation has gone
well, or show an error message otherwise:
$ runhaskell <<< 'import FRP.Yampa; main = putStrLn "Success"'
Examples
(Back to top)
Getting Yampa to run is trivial. FRP is about values that change over time. In Yampa, a system is defined by a signal function (SF), which determines how the varying input and the varying output relate.
Code can be written in multiple styles: applicative style, arrowized style, and just plain arrow combinators. All three are compatible and interchangeable.
For example, the following signal function takes a value, integrates it, and then divides that value by the current time:
{-# LANGUAGE Arrows #-}
import FRP.Yampa
signalFunction :: SF Double Double
signalFunction = proc x -> do
y <- integral -< x
t <- time -< ()
returnA -< y / t
This signal function says that the output signal is the integral y
of the
input signal x
, divided by the time t
. The elements between <-
and -<
are always signal functions (in this case, integral
and time
are signal
functions used to define another signal function).
The example above is written in arrow syntax and uses a Haskell extension called Arrows. If you are unhappy using arrow syntax, you can implement the same behavior using applicative style and/or arrow combinators:
-- Applicative style
signalFunction1 :: SF Double Double
signalFunction1 = (/) <$> integral <*> time
-- Functional style with arrow combinators
signalFunction2 :: SF Double Double
signalFunction2 = (integral &&& time) >>^ (/)
All three are equivalent, and it's a matter of which one you like best.
To run this example, we need to provide the inputs, the times, and consume the output:
firstSample :: IO Double -- sample at time zero
firstSample =
return 1.0 -- time == 0, input == 1.0
nextSamples :: Bool -> IO (Double, Maybe Double)
nextSamples _ =
return (0.1, Just 1.0) -- time delta == 0.1s, input == 1.0
output :: Bool -> Double -> IO Bool
output _ x = do
print x -- print the output
return False -- just continue forever
This is a trivial example, since the integral of the constant function 1.0 over time, divided by the time, is always 1.0! Nevertheless, we are now ready to run!
ghci> reactimate firstSample nextSamples output signalFunction
1.0
1.0
1.0
1.0
1.0
1.0
...
There is a directory with examples, which includes two basic SDL examples and one with using a Nintendo Wii Remote. You can install them with:
$ cabal update
$ cabal install Yampa -fexamples
Related projects
(Back to top)
Games and applications
(Back to top)
- cuboid: 3D puzzle game with GLUT.
- Frag: a 3D first person shooting game.
- hamball: 3D, LAN FPS game of hamster balls flying around and shooting lasers written in Haskell.
- Haskanoid: a game that uses SDL multimedia, wiimote and kinect. It's cross platform and works in desktop, mobile, and web (compiled with GHCJS).
- Haskelloids: a reproduction of the Atari 1979 classic "Asteroids"
- LaneWars: Top-down MOBA game with online multiplayer.
- MandelbrotYampa: a "hello world" using SDL2, Yampa and OpenGL.
- Pang-a-lambda: 2D arcade game inspired by the classic super-pang.
- Peoplemon: a role playing game.
- Spaceinvaders: Re-write of the classic space invaders.
- The Bearriver Arcade: A couple of arcade games made using bearriver, a library that implements the Yampa API.
- Yampa-2048: an implementation of the game 2048 using Yampa and Gloss.
- YampaShooter: Top-down team based networked tank game.
- YampaSynth: Software synthesizer.
- YFrob: Yampa-based library for programming robots.
A more comprehensive list can be obtained using the reverse dependency finder (http://packdeps.haskellers.com/reverse/Yampa), but only programs uploaded to hackage are listed.
![]() |
![]() |
![]() |
---|---|---|
Haskanoid, SDL cross-platform arkanoid. | Peoplemon, a role playing game | Yampa2048, a gloss board game |
Use in industry
(Back to top)
Keera Studios uses Yampa to create Haskell games available on Google Play for Android and iTunes for iOS:
Backends
(Back to top)
Yampa is backend agnostic, you can ultimately connect it to any backend you want. Existing backends include:
- SDL (see Haskanoid for an example)
- SDL2 (see yampa-sdl2)
- OpenGL / GLUT (see Haskell-OpenGL-Tutorial).
- GLFW (see yampa-glfw)
- WX (see wxHaskell)
- HTML Canvas via JS Dom (for an example, see haskanoid's GHCJS branch)
- HTML5 Canvas via blank-canvas (see yampa-canvas)
- Gloss (see yampa-gloss)
- Diagrams (see diagrams example)
- Keera Hails (reactive programming framework with GTK, WX, Qt, Android, iOS and HTML support).
Testing
(Back to top)
Yampa comes with a sophisticated testing library that allows you to use QuickCheck to test your games, and use a time-travel debugger. These features are described in the paper Testing and Debugging Functional Reactive Programming.
You can find the additional projects at:
Other projects
(Back to top)
- Bearriver: API-compatible Yampa replacement built on top of dunai using Monadic Stream Functions.
- Dunai: An FRP implementation inspired by Yampa that extends SFs with a monad.
- Functional Reactive Virtual Reality: a fork of Yampa with extensions for VR.
- graphui: Attempt to implement Graphui.
- Haskell-OpenGL-Tutorial same as here: Visually attractive mandelbrot implementation.
- Keera Hails: Backend for reactive framework with GTK, WX, Qt, Android, iOS and HTML support, with a library to connect Yampa signal functions.
Documentation
(Back to top)
API documentation and tutorials
(Back to top)
The API of Yampa is thoroughly documented on hackage. Documentation is also available in the Haskell wiki page for Yampa.
Publications
(Back to top)
-
Extensible and Robust Functional Reactive Programming (Ivan Perez; 2017)
-
Testing and Debugging Functional Reactive Programming (Ivan Perez and Henrik Nilsson; 2017)
-
Functional Reactive Programming, Refactored (Ivan Perez, Manuel Bärenz, and Henrik Nilsson; 2016)
-
Safe Functional Reactive Programming through Dependent Types (Neil Sculthorpe and Henrik Nilsson; 2009)
-
Push-Pull Functional Reactive Programming (Conal Elliott; 2009)
-
Switched-on Yampa: Declarative Programming of Modular Synthesizers (George Giorgidze and Henrik Nilsson; 2008)
-
Demo-outline: Switched-on Yampa: Programming Modular Synthesizers in Haskell (George Giorgidze and Henrik Nilsson; 2007)
-
Dynamic Optimization for Functional Reactive Programming using Generalized Algebraic Data Types (Henrik Nilsson; 2005)
-
The Yampa Arcade (Antony Courtney, Henrik Nilsson, and John Peterson; 2003)
-
Arrows, Robots, and Functional Reactive Programming (Paul Hudak, Antony Courtney, Henrik Nilsson, and John Peterson; 2002)
-
Functional Reactive Programming, Continued (Henrik Nilsson, Antony Courtney, and John Peterson; 2002)
-
Genuinely Functional User Interfaces (Antony Courtney and Conal Elliott; 2001)
-
See also:
- Collection of Yampa diagrams
- Henrik Nilsson's publications
- Ivan Perez's publications
- First Year PhD Report (Ivan Perez, 2014), chapter 3 includes a review of FRP and outlines some existing issues.
Contributions
(Back to top)
Feel free to open new issues. We are looking for:
- New games and applications that use Yampa.
- Libraries that help use Yampa in a particular domain, or apply it to a specific platform.
- Papers that mention Yampa.
- Extensions to write programs that are not currently possible or convenient to capture.
- Bug fixes.
- Improvements to make the code demonstrably faster or smaller.
If this library helps you, you may want to consider buying the maintainer a cup of coffee.
Structure and internals
(Back to top)
This project is split in two:
- Yampa: FRP library.
- Yampa-test: a testing layer for Yampa.
Yampa's unit tests are mostly implemented as tests inside the yampa-test
library. The module hierarchy of yampa-test/tests/Test
mirrors that of Yampa.
A directory yampa/examples
contains a number of examples of Yampa programs,
some of which can be installed with the flag -fexamples
.
Style
(Back to top)
We follow this style guide for the Haskell code and this style guide for Cabal files.
Version control
(Back to top)
We follow git flow. In addition:
- Please document your commits clearly and separately.
- Always refer to the issue you are fixing in the commit summary line with the
text
Refs #<issue_number>
at the end. - If there is no issue for your change, then open an issue first and document what you are trying to achieve/improve/fix.
- Do not address more than one issue per commit or per PR. If two changes are not directly related to one another, they belong in different PRs, issues and commits.
- Document what you did in the respective CHANGELOGs in a separate commit before you send a PR.
- Make sure your changes conform to the coding style.
See the recent repo history for examples of this process. Using a visual repo
inspection tool like gitk
may help.
Versioning model
(Back to top)
The versioning model we use is the standard in Haskell packages. Versions have
the format <PUB>.<MAJOR>.<MINOR>(.<PATCH>)?
where:
-
<PUB>
is just a way to signal important milestones or used for promotional reasons (to indicate a major advancement). A zero on this position has no special meaning. -
<MAJOR>
increases on incompatible API changes. -
<MINOR>
increases on backwards-compatible changes. -
<PATCH>
(optional) increases on small changes that do not affect behavior (e.g., documentation).
History
(Back to top)
This library was created by Henrik Nilsson and Antony Courtney in 2002, while working at Yale's Haskell group, led by Paul Hudak. The design and implementation benefited from frequent discussions with other members of the group, including also John Peterson. From 2008 to 2012, it was maintained by George Giorgidze. In 2014, maintenance was passed to Ivan Perez.
Yampa is the longest standing FRP implementation in Haskell still in use. It has seen and continues to see abundant use in industry, research, and academia. We invite you to be part of this incredible community project as a user, a contributor, and overall supporter.
Yampa is named after the Yampa river in Colorado, USA.