Yampa Documentation

repository·develop·Indexed 19 days ago

https://github.com/ivanperez-keera/yampa

A domain-specific language embedded in Haskell for programming hybrid systems (mixed discrete-time and continuous-time) using Functional Reactive Programming (FRP) principles. It centers on Signal Functions (SF) and supports arrowized, applicative, and functional programming styles. The library is backend agnostic, supporting SDL, OpenGL, GLFW, WX, HTML5, Gloss, and others, and includes a dedicated testing layer called yampa-test with QuickCheck integration and a time-travel debugger.

Tokens
4K
Snippets
8
Records
13
Agent score
17%

What's inside Yampa

  1. Core Concept: Signal Functions (SF)

    develop

    In Yampa, a system is defined by a Signal Function (SF). An SF determines how varying inputs relate to varying outputs over time.

    Programming in Yampa supports three interchangeable styles:

    1. Arrowized style: Uses proc notation and arrow syntax (requires {-# LANGUAGE Arrows #-}).
    2. Applicative style: Uses standard applicative operators like <$> and <*>.
    3. Functional style: Uses arrow combinators.

    Example of an SF that integrates an input and divides it 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
  2. Understand the Yampa project structure

    develop

    The project is divided into two primary components:

    1. Yampa: The core Functional Reactive Programming (FRP) library.
    2. Yampa-test: A dedicated testing layer for Yampa. Most unit tests for the main library are implemented within yampa-test. The module hierarchy in yampa-test/tests/Test is designed to mirror the hierarchy of the main Yampa library.

    Additionally, the yampa/examples directory contains various Yampa program examples. Some of these examples can be installed using the -fexamples flag during compilation.

  3. Testing and Debugging with Yampa

    develop

    Yampa includes a sophisticated testing library designed for functional reactive programming. It supports:

    • QuickCheck Integration: Use property-based testing to verify game logic and signal functions.
    • Time-travel Debugger: Allows you to step through time to debug reactive behaviors.

    For more details on the methodology, refer to the paper Testing and Debugging Functional Reactive Programming.

  4. Install Yampa examples

    develop

    To install the example programs provided in the repository, use the -fexamples flag during the compilation/installation process.

    # Example usage of the flag during installation
    # (Exact command depends on your build tool, e.g., cabal or stack)
    # cabal install yampa -fexamples
  5. Install Yampa via Cabal

    develop

    To install Yampa, ensure you have a Haskell compiler (GHC) installed. You can then use cabal to install the library from Hackage.

    To install the library with examples (such as SDL examples), use the -fexamples flag.

    $ cabal update
    $ cabal install --lib Yampa
    
    # To include examples
    $ cabal install Yampa -fexamples
  6. Implement Signal Functions in different styles

    develop

    Yampa allows you to write the same logic using different syntax styles. The following three implementations are equivalent:

    Arrow Syntax (requires Arrows extension):

    signalFunction :: SF Double Double
    signalFunction = proc x -> do
      y <- integral -< x
      t <- time     -< ()
      returnA -< y / t

    Applicative Style:

    signalFunction1 :: SF Double Double
    signalFunction1 = (/) <$> integral <*> time

    Arrow Combinators (Functional Style):

    signalFunction2 :: SF Double Double
    signalFunction2 = (integral &&& time) >>^ (/)
    -- Applicative style
    signalFunction1 :: SF Double Double
    signalFunction1 = (/) <$> integral <*> time
    
    -- Functional style with arrow combinators
    signalFunction2 :: SF Double Double
    signalFunction2 = (integral &&& time) >>^ (/)
  7. Run a Yampa system with reactimate

    develop

    To execute a signal function, use the reactimate function. This requires providing three components:

    1. An initial input function (IO a).
    2. An input sensing function (Bool -> IO (Double, Maybe a)) which provides the time delta and the next input.
    3. An output consumption function (Bool -> b -> IO Bool) which processes the output and determines if the loop should continue.

    Example execution loop:

    -- sample at time zero
    firstSample :: IO Double
    firstSample = return 1.0
    
    -- time delta == 0.1s, input == 1.0
    nextSamples :: Bool -> IO (Double, Maybe Double)
    nextSamples _ = return (0.1, Just 1.0)
    
    -- print the output
    output :: Bool -> Double -> IO Bool
    output _ x = do
      print x
      return False
    
    -- Run: reactimate firstSample nextSamples output signalFunction
  8. Visual diagrams for Yampa combinators and switches

    develop

    The following Yampa functions and concepts have corresponding visual diagrams to help understand their signal flow and behavior. These diagrams are useful for mental modeling of Functional Reactive Programming (FRP) structures.

    Basic Combinators

    • arr: Array/lifting function.
    • (>>>): Composition operator.
    • loop: Feedback/looping mechanism.
    • (&&&): Parallel fanout.
    • Signal Function network: Visualizes varying structures in an SF network.

    Switching Functions

    • kSwitch
    • pSwitchB
    • pSwitch
    • rpSwitchB
    • rpSwitch
    • rSwitch
    • switch

    Core Concepts

    • Basic Signal Functions: Overview of standard SFs.
    • Reactimate Activity: Visualizes the high-level activity of the reactimate loop.
    • Reactimate Dataflow: Visualizes how data flows through the reactimate process.
    | Function(s)             | Diagram                             | Format | Author           | License       |
    |-------------------------|-------------------------------------|--------|------------------|---------------|
    | `arr`                   | [![arr](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/combinator-arr-narrow.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/dia/combinator-arr-narrow.dia)       | dia    | Henrik Nilsson   | Public Domain |
    | `(>>>)`                 | [![(>>>)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/combinator-compose-narrow.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/dia/combinator-compose-narrow.dia)   | dia    | Henrik Nilsson   | Public Domain |
    | `loop`                  | [![Loop](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/combinator-loop-narrow.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/dia/combinator-loop-narrow.dia)      | dia    | Henrik Nilsson   | Public Domain |
    | `(&&&)`                 | [![&&&](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/combinator-parfanout-narrow.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/dia/combinator-parfanout-narrow.dia) | dia    | Henrik Nilsson   | Public Domain |
    | Signal Function network | [![SF network](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/varying_structure.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/dia/varying_structure.dia)           | dia    | Henrik Nilsson   | Public Domain |
    | `kSwitch`               | [![kSwitch](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_kSwitch.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_kSwitch.svg)               | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | `pSwitchB`              | [![pSwitchB](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_pSwitchB.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_pSwitchB.svg)              | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | `pSwitch`               | [![pSwitch](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_pSwitch.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_pSwitch.svg)               | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | `rpSwitchB`             | [![rpSwitchB](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_rpSwitchB.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_rpSwitchB.svg)             | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | `rpSwitch`              | [![rpSwitch](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_rpSwitch.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_rpSwitch.svg)               | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | `rSwitch`               | [![rSwitch](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_rSwitch.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_rSwitch.svg)               | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | `switch`                | [![switch](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/Yampa_switch.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/Yampa_switch.svg)                | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | Basic Signal Functions  | [![yampa_signalfunctions](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/yampa_signalfunctions.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/yampa_signalfunctions.svg)       | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | Reactimate Activity     | [![yampa_reactimate_activity](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/yampa_reactimate_activity.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/yampa_reactimate_activity.svg)   | SVG    | Gerold Meisinger | CC BY-NC-SA   |
    | Reactimate Dataflow     | [![yampa_reactimate_dataflow](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/png/yampa_reactimate_dataflow.png)](http://www.cs.nott.ac.uk/~psxip1/images/frp-diagrams/svg/yampa_reactimate_dataflow.svg)     | SVG    | Gerold Meisinger | CC BY-NC-SA   |
  9. Related FRP Projects

    develop

    If Yampa does not perfectly fit your needs, consider these related projects:

    • Dunai: An FRP implementation inspired by Yampa that extends Signal Functions (SFs) with a monad.
    • Bearriver: An API-compatible Yampa replacement built on top of dunai using Monadic Stream Functions.
    • Functional Reactive Virtual Reality (FRVR): A fork of Yampa with extensions specifically for VR applications.