Yampa
Functional Reactive Programming domain-specific language for efficient hybrid systems
Install / Use
/learn @ivanperez-keera/YampaREADME
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
</div>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
<sup>(Back to top)</sup>
Pre-requisites
<sup>(Back to top)</sup>
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
<sup>(Back to top)</sup>
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
<sup>(Back to top)</sup>
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
<sup>(Back to top)</sup>
Games and applications
<sup>(Back to top)</sup>
- 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.
- Yampa - Game of Life: an implementation of Game of Life using SDL2 and OpenGL.
- 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.
| <img src="https://raw.githubusercontent.com/ivanperez-keera/haskanoid/master/screenshots/android.gif?raw=true" width="200" alt="Haskanoid Video" style="max-width:200px;"> | <img src="https://media.giphy.com/media/SsBOvldu1FnSyNZW1z/giphy.gif" width="200" alt="Peoplemon by Alex Stuart" style="max-width: 200px;"> | <img src="http://ksaveljev.github.io/2048.gif" width="110" alt="Space Invaders" style="max-width: 110px;"> | |-------------------------------------------|---------------|-------------------------| | Haskanoid, SDL cross-platform arkanoid. | Peoplemon, a role playing game | Yampa2048, a gloss board game |
Use in industry
<sup>(Back to top)</sup>
Keera Studios uses Yampa to create Haskell games available on Google Play for Android and iTunes for iOS:
<table> <tr> <td> <p align="center"> Magic Cookies! <br /><br /> <a href="http://magiccookies.haskell.games"> <img src="https://raw.githubusercontent.com/keera-studios/magic-cookies/master/screencap.gif" height="auto" alt="Magic Cookies! Video" style="max-height:175px;"></a> <img width="441" height="1"> <br /> <sup>Copyright © 2015 - 2020 Keera Studios Ltd. All Rights Reserved.</sup> <br /> <a href="https://itunes.apple.com/us/app/magic-cookies/id1244709871"> <img src="https://raw.githubusercontent.com/edent/SuperTinyIcons/master/images/svg/apple.svg" width="32" height="32"></a> <a href="https://play.google.com/store/apps/details?id=uk.co.keera.games.magiccookies"> <img src="https://raw.githubusercontent.com/edent/SuperTinyIcons/master/images/svg/google_play.svg" width="32" height="32"></a> </p> </td> <td> <p align="center"> Magic Cookies 2! <br /><br /> <a href="http://magiccookies2.haskell.games"> <img src="https://raw.githubusercontent.com/keera-studios/magic-cookies2/master/screencap.gif" height="auto" alt="Magic Cookies 2! Video" style="max-height:175px;"></a> <img width="441" height="1"> <br /> <sup>Copyright © 2015 - 2022 Keera Studios Ltd. All Ri