ivanperez-keera / Yampa

Functional Reactive Programming domain-specific language for efficient hybrid systems
449 stars 51 forks source link
android frp functional-reactive-programming game haskell ios ipad iphone mobile multimedia opengl sdl yampa
# Yampa [![Build Status](https://api.travis-ci.com/ivanperez-keera/Yampa.svg?branch=master)](https://app.travis-ci.com/github/ivanperez-keera/Yampa) [![Version on Hackage](https://img.shields.io/hackage/v/Yampa.svg)](https://hackage.haskell.org/package/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](#installation) • [Examples](#examples) • [Related projects](#related-projects) • [Documentation](#documentation) • [Contributions](#contributions) • [History](#history)

Features

Table of Contents

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)

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 Video Peoplemon by Alex Stuart Space Invaders
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:

Magic Cookies!

Magic Cookies! Video
Copyright © 2015 - 2020 Keera Studios Ltd. All Rights Reserved.
  

Magic Cookies 2!

Magic Cookies 2! Video
Copyright © 2015 - 2022 Keera Studios Ltd. All Rights Reserved.
  

Enpuzzled

Enpuzzled Video
Copyright © - 2017 - Keera Studios Ltd - All Rights Reserved.
  

Keera, Keera Studios, Magic Cookies, Magic Cookies 2, the Magic Cookies logo, the Magic Cookies 2 logo, the Magic Cookies splash screen, the Magic Cookies 2 splash screen, Enpuzzled, the Enpuzzled splash screen, and the Enpuzzled logo are trademarks of Keera Studios Ltd. Google Play and the Google Play logo are trademarks of Google LLC. Apple, the Apple logo, iPhone, and iPad are trademarks of Apple Inc., registered in the U.S. and other countries and regions. App Store is a service mark of Apple Inc.

Backends

(Back to top)

Yampa is backend agnostic, you can ultimately connect it to any backend you want. Existing backends include:

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)

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)

Contributions

(Back to top)

If this library helps you, you may want to consider buying the maintainer a cup of coffee.

Discussions, issues and pull requests

(Back to top)

Discussions

If you have any comments, questions, ideas, or other topics that you think will be of interest to the Yampa community, start a new discussion here. Examples include:

Issues

If a specific change is being proposed (either a new feature or a bug fix), you can open an issue documenting the proposed change here.

If you are unsure about whether your submission should be filed as an issue or as a discussion, file it as a discussion. We can always move it later.

Pull requests

Once we determine that an issue will be addressed, we'll decide who does it and when the change will be added to Yampa. Even if you implement the solution, someone will walk you through the steps to ensure that your submission conforms with our version control process, style guide, etc. More information on our process is included below.

Please, do not just send a PR unless there is an issue for it and someone from the Yampa team has confirmed that you should address it. The PR is very likely to be rejected, and we really want to accept your contributions, so it will make us very sad. Open a discussion / issue first and let us guide you through the process.

Structure and internals

(Back to top)

This project is split in two:

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.

Yampa also includes some benchmarks as part of the main library. You are encouraged to use them to evaluate your pull requests, and to improve the benchmarks themselves.

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:

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:

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.