GithubHelp home page GithubHelp logo

elerea's Introduction

Introduction

Elerea (Eventless reactivity) is a tiny discrete time functional reactive programming (FRP) system without the notion of event-based switching and sampling, but with first-class signals (time-varying values). Reactivity is provided through various higher-order constructs that also allow the user to work with arbitrary time-varying structures containing live signals. Signals have precise and simple denotational semantics.

Stateful signals can be safely generated at any time through a monadic interface, while stateless combinators can be used in a purely applicative style. Elerea signals can be defined recursively, and external input is trivial to attach. The library comes in two major variants:

  • Simple: signals are plain discrete streams isomorphic to functions over natural numbers;
  • Param: adds a globally accessible input signal for convenience;

This is a minimal library that defines only some basic primitives, and you are advised to install elerea-examples as well to get an idea how to build non-trivial systems with it. The examples are separated in order to minimise the dependencies of the core library. The dow package contains a full game built on top of the simple variant.

The basic idea of the implementation is described in the WFLP 2010 paper Efficient and Compositional Higher-Order Streams.

Related projects

  • Dungeons of Wor: a simple old-school arcade game programmed with Elerea to serve as a non-trivial example for using the library.
  • Euphoria: a complex reactive framework built around Elerea.
  • Helm: a game engine that uses Elerea for describing interactions and behaviours.
  • LambdaCube 3D: a purely functional GPU pipeline description language, whose showcases mostly rely on Elerea.

elerea's People

Contributors

cobbpg avatar takano-akio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elerea's Issues

Serialisation of program state

It should be possible to load/save the run-time state of signal networks. This would open the door to a bunch of interesting features, e.g. undo, replay, or dynamic loading of reactive modules without full recompilation. Unfortunately, the current interface makes this impossible, since everything is forced into lambdas.

'snapshot' glitch

For me the behaviour of snapshot is counterintuitive (and makes a bit harder to model elerea in another FRP library).

In the pure model, snapshot is the identity function.
However, it can change the order of IO effects:

example n = do
    smp <- start $ do
        s <- effectful $ print "?"
        replicateM_ n $ snapshot s
        return s
    print "!"
    smp

Sample outputs:

example 0    -->   !?
example 1    -->   ?!
example 2    -->   ?!

I guess the current behaviour is the intended behaviour.
From my point of view it would be more consistent to get always "?!", kind of pre-cache all signal values when running the SignalGen monad.
This way I think the order of side-effects would be more predictable. Also this is needed to make the Signal monad commutative:

m1 :: Signal a
m2 :: Signal b
liftA2 (,) m1 m2   ~~  swap <$> (liftA2 (,) m2 m1)

GC related performance issue

In the following code unsafePerformIO stands for a long computation.

long k = do
    i <- newIORef 0
    smp <- start $ do
        generator $ pure $ do
            s1 <- generator $ pure $ return $! unsafePerformIO $ readIORef i >>= writeIORef i . (+1)
            snapshot s1
    replicateM_ k smp
    readIORef i >>= print

With GHC 7.8.4, compiler options -O2, I get the following numers:

long 0    ->    0
long 1    ->    1
long 2    ->    3
long 3    ->    6
long 4    ->    10
...
long 10000    ->    238726    

For small inputs it is quadratic, for large ones less than quadratic (maybe GC related).

entangled 'start' calls

starts below returns 1 instead of 0:

starts = do
    c <- join $ start $ do
        c <- stateful 0 (+1)
        return $ pure c
    join $ start $ do
        c2 <- stateful 0 (+1)
        return $ liftM2 (+) c c2

Intuitively, the first start creates a counter and join do one sampling. Because no other sampling will ever happen, the value of this counter should be 0 in any computation.
Then the second start creates another counter and join do one sampling. Moreover, the second start combines the values of the counters which sould be 0.

Strange behaviour of 'effectful'

In the following program I use effectful to print something on every iteration. However it only prints a few times (exact number of times varies from run to run) and then stops. The code uses the driveNetwork function from elerea-examples:

import Control.Applicative
import Control.Monad
import Control.Concurrent (threadDelay)

import FRP.Elerea.Param

main = do
    network <- start $ do
        effectful $ print "test"
        return . return . return $ ()

    driveNetwork network $ do
        threadDelay 100000
        return $ Just undefined

driveNetwork network driver = do
  dt <- driver
  case dt of
    Just dt -> do join (network dt)
                  driveNetwork network driver
    Nothing -> return ()

I'm using GHC 7.6.3 (Haskell Plattform) on Windows. Sometimes it takes a while until it stops printing, but it always stops at some point...

Fail on improper use

This is a feature request.

I wish elerea would fail on improper use.
Of course, the best would be to fail during compilation but if it is not feasable still better to fail in runtime than silently go on.
I think this way elerea users would be less surprised.

For example, consider the following code:

unspecified = do
    (sg, snk) <- externalMulti
    snk 0
    join $ start $ do
        s1 <- sg
        s2 <- sg
        return $ liftM2 (++) s1 s2

I think unspecified should return [0,0] but it returns [0].
This is not a bug, because the documentation of externalMulti sais that the generator can only be used once so I cannot complain.

'external' glitch

In a multithreaded environment use of external can cause a glitch.

The following program returns False instead of True:

-- slowFib is used to force a specific unlucky scheduling
slowFib 0 = 0
slowFib 1 = 1
slowFib n = slowFib (n-1) + slowFib (n-2)

externalGlitch = do
    (sig, snk) <- external 0
    forkIO $ slowFib 20 `seq` snk 1
    join $ start $ return $ liftM2 (==) sig (slowFib 22 `seq` sig)

I guess this is a bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.