Coder Social home page Coder Social logo

ivanperez-keera / dunai Goto Github PK

View Code? Open in Web Editor NEW
191.0 13.0 29.0 17.57 MB

Classic FRP, Arrowized FRP, Reactive Programming, and Stream Programming, all via Monadic Stream Functions

Haskell 100.00%
haskell haskell-library frp frp-library functional-programming functional-reactive-programming game monad arrows abstraction

dunai's Introduction

Dunai

Build Status Version on Hackage

Dunai is a generalized reactive programming library on top of which other variants like Classic FRP, Arrowized FRP and Reactive Values can be implemented.

InstallationExamplesDocumentationRelated projectsTechnical informationContributionsHistory

Features

  • Intuitive syntax and semantics.

  • Composition of effects via use of different monads and transformers.

  • Isolation of effectful and effect-free reactive functions at type level.

  • Time-free (time is not explicitly included) and time-able (time can be added).

  • Fully extensible.

  • Can be used to implement other FRP libraries/flavors on top.

  • Supports applicative, functional and arrowized style.

  • Programs can be tested with QuickCheck and debugged using Haskell Titan.

Table of Contents

Installation

(Back to top)

Pre-requisites

(Back to top)

To use Dunai, you must have a Haskell compiler installed (GHC). We currently support GHC versions 7.6.3 to 9.8.1. It likely works with other versions as well.

On Debian/Ubuntu, both 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 Dunai by executing:

$ cabal update
$ cabal install --lib dunai

Running the following will print the word Success if installation has gone well, or show an error message otherwise:

$ runhaskell <<< 'import Data.MonadicStreamFunction; main = putStrLn "Success"'

Examples

(Back to top)

Open a GHCi session and import the main Dunai module:

$ ghci
ghci> import Data.MonadicStreamFunction

An MSF is a time-varying transformation applied to a series of inputs as they come along, one by one.

Use the primitive arr :: (a -> b) -> MSF m a b to turn any pure function into an MSF that applies the given function to every input. The function embed :: MSF m a b -> [a] -> m [b] runs an MSF with a series of inputs, collecting the outputs:

ghci> embed (arr (+1)) [1,2,3,4,5]
[2,3,4,5,6]

MSFs can have side effects; hence the m that accompanies the type MSF in the signatures of arr and embed. The function arrM turns a monadic function of type a -> m b into an MSF that will constantly apply the function to each input.

For example, the function print takes a value and prints it to the terminal (a side effect in the IO monad), producing an empty () output. Elevating or lifting print into an MSF will turn it into a processor that prints each input passed to it:

ghci> :type print
print :: Show a => a -> IO ()
ghci> :type arrM print
arrM print :: Show a => MSF IO a ()

If we now run that MSF with five inputs, all are printed to the terminal:

ghci> embed (arrM print) [1,2,3,4,5]
1
2
3
4
5
[(), (), (), (), ()]

As we can see, after all side effects, embed collects all the outputs, which GHCi shows at the end.

When we only care about the side effects and not the output list, we can discard it with Control.Monad.void. (Dunai provides an auxiliary function embed_ for the same purpose.)

ghci> import Control.Monad (void)
ghci> void $ embed (arrM print) [1,2,3,4,5]
1
2
3
4
5

MSFs can be piped into one another with the functions (>>>) or (.), so that the output of one MSF is fed as input to another MSF at each point:

ghci> void $ embed (arr (+1) >>> arrM print) [1,2,3,4,5]
2
3
4
5
6

A monadic computation without arguments can be lifted into an MSF with the function constM:

ghci> :type getLine
getLine :: IO String
ghci> :type constM getLine
constM getLine :: MSF IO a String

This MSF will get a line of text from the terminal every time it is called, which we can pipe into an MSF that will print it back.

ghci> void $ embed (constM getLine >>> arrM putStrLn) [(), ()]
What the user types, the computer repeats.
What the user types, the computer repeats.
Once again, the computer repeats.
Once again, the computer repeats.

Notice how we did not care about the values in the input list to embed: the only thing that matters is how many elements it has, which determines how many times embed will run the MSF.

Simulations can run indefinitely with the function reactimate :: MSF m () () -> m (), which is useful when the input to the MSFs being executed is being produced by another MSFs, like in the case above with constM getLine producing inputs consumed by arrM putStrLn:

ghci> reactimate (constM getLine >>> arr reverse >>> arrM putStrLn)
Hello
olleH
Haskell is awesome
emosewa si lleksaH
^C

Dunai has a very extensive API and supports many programming styles. MSFs are applicatives, so we can transform them using applicative style, and they are categories, so they can be piped into one another with Control.Category.(.). For example, the line above can also be written as:

ghci> reactimate (arrM putStrLn . (reverse <$> constM getLine))

which is equivalent to:

ghci> reactimate (arrM putStrLn . fmap reverse . constM getLine)

Other writing styles (e.g., arrow notation) are also supported. This versatility makes it possible for you to use the notation you feel most comfortable with.

MSFs are immensely expressive. With MSFs, you can implement stream programming, functional reactive programming (both classic and arrowized), reactive programming, and reactive values, among many others. The real power of MSFs comes from the ability to carry out temporal transformations (e.g., delays), to apply different transformations at different points in time, and to work with different monads. See the documentation below to understand how capable they are.

Documentation

(Back to top)

Publications

(Back to top)

The best introduction to the fundamentals of Monadic Stream Functions is:

The following papers are also related to MSFs:

Videos

(Back to top)

Related projects

(Back to top)

Games

(Back to top)

  • The Bearriver Arcade. Fun arcade games made using Bearriver.

  • Haskanoid. Haskell breakout game implemented using the Functional Reactive Programming library Yampa (compatible with Dunai/Bearriver).

Libraries

  • ivanperez-keera/Yampa: a full FRP implementation that has been used extensively in academia, open source and industry.

  • turion/rhine: extension of Dunai with type-level clocks and explicit coordination.

  • keera-studios/haskell-titan: an advanced, interactive testing framework with support for step-by-step execution and record-and-replay. Haskell-titan supports connecting to dunai systems via its Yampa-compatible interface library bearriver, via a flag in the libraries titan-debug-yampa and titan-record-yampa.

Technical information

(Back to top)

Performance

(Back to top)

Simpler games will be playable without further optimisations. For example, the game haskanoid works well with Dunai/Bearriver. You can try it with:

$ git clone https://github.com/ivanperez-keera/haskanoid.git
$ cd haskanoid/
$ cabal install -f-wiimote -f-kinect -fbearriver

It uses unaccelerated SDL 1.2, the speed is comparable to Yampa's:

$ haskanoid
Performance report :: Time per frame: 13.88ms, FPS: 72.04610951008645, Total running time: 1447
Performance report :: Time per frame: 16.46ms, FPS: 60.75334143377886, Total running time: 3093
Performance report :: Time per frame: 17.48ms, FPS: 57.20823798627002, Total running time: 4841
Performance report :: Time per frame: 19.56ms, FPS: 51.12474437627812, Total running time: 6797
Performance report :: Time per frame: 19.96ms, FPS: 50.100200400801604, Total running time: 8793
Performance report :: Time per frame: 19.44ms, FPS: 51.440329218106996, Total running time: 10737

It runs almost in constant memory, with about 50% more memory consumption than with Yampa: 200k for Yampa and 300K for Dunai/Bearriver. (There is very minor leaking, probably we can fix that with seq.)

We have obtained different figures tracking different modules. In the paper, we provided figures for the whole game, but we need to run newer reliable benchmarks including every module and only definitions from FRP.Yampa, FRP.BearRiver and Data.MonadicStreamFunction.

Dunai 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.

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 Dunai community, start a new discussion here. Examples include:

  • You've created a new game or application that uses Dunai or BearRiver.
  • You've written or found a library that helps use Dunai/BearRiver in a particular domain, or apply it to a specific platform.
  • You've written or found a paper that mentions Dunai/BearRiver.
  • You have an idea for an extension that will enable writing programs that are not currently possible or convenient to capture.
  • You think you've found a bug.
  • You want to propose an improvement (e.g., make the code faster or smaller).
  • You have a question.
  • Something in the documentation, a tutorial or a Dunai / BearRiver / FRP paper is unclear.
  • You like the project and want to introduce yourself.

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 Dunai. 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 Dunai 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 three parts:

  • Dunai: a reactive library that combines monads and arrows.
  • BearRiver: Yampa implemented on top of Dunai.
  • Examples: ballbounce
    • sample applications that work both on traditional Yampa and BearRiver.

Dunai 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.

Style

(Back to top)

We follow this style guide.

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. This commit should be the last one in the PR.
  • If your commit pertains to one package only, name the package at the beginning of the summary line with the syntax <package_name>: <...rest_of_summary...>.
  • 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 Dunai was created by Ivan Perez and Manuel Baerenz. It is named after the Dunai (aka. Danube, or Дунай) river, one of the main rivers in Europe, originating in Germany and touching Austria, Slovakia, Hungary, Croatia, Serbia, Romania, Bulgaria, Moldova and Ukraine.

Other FRP libraries, like Yampa and Rhine, are named after rivers. Dunai has been chosen due to the authors' relation with some of the countries it passes through, and knowing that this library has helped unite otherwise very different people from different backgrounds.

dunai's People

Contributors

direwolf707 avatar dynomite567 avatar geroldmeisinger avatar ggreif avatar ivanperez-keera avatar linearity avatar miguel-negrao avatar rizary avatar thalerjonathan avatar turion avatar walseb 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  avatar  avatar  avatar  avatar  avatar

dunai's Issues

Dunai fails to compile with ghc 7.8.4 / base 4.7

Base 4.7, included with GHC 7.8.4 (which I still use extensively for game programming), does not automatically export Control.Applicative from Control.Monad. It also does not automatically enforce the Functor constraint on Applicative instances.

In order to make dunai compile with older versions of GHC, a few extra imports and type signatures are needed.

Cross-reference and code highlight documentation

We should add cross-references in the haddock, e.g. writing 'MSF' in most places instead of MSF or @MSF@. Where no useful reference exist, still prefer monospace @someHaskellConcept@ over someHaskellConcept.

Import all instances from Data.MonadicStreamFunction.Instances.*, or avoid orphan instances

Currently we have orphan instances in several modules Data.MonadicStreamFunction.Instances.*. Some of them (ArrowChoice, ArrowLoop, ArrowPlus) are imported in Data.MonadicStreamFunction (the module usually imported by users) and some others (Num, VectorSpace etc.) are not. This creates a few problems:

  1. The haddock documentation does not display any instances for MSF in the place where it's defined (Data.MonadicStreamFunction.Core), or in Data.MonadicStreamFunction. The user would have to visit the submodule Data.MonadicStreamFunction.Instances.* in order to even find out about it.
  2. The user doesn't have the instances Num etc. until they explicitly import the corresponding submodule.
  3. Orphan instances are generally frowned upon (although they probably won't do any harm here).

Problem 2. would be solved by importing all instances from all submodules Data.MonadicStreamFunction.*.
Problem 1. might be solved by somehow explicitly reexporting the name MSF in Data.MonadicStreamFunction, but I don't know haddock well enough. Right now it is halfway solved by explicit documentation in Data.MonadicStreamFunction.

The solution to all those problems, that a vanilla haskell package maintainer might bring forward is just to avoid orphan instances by putting all instances into Data.MonadicStreamFunction.Core, directly where MSF is defined. There is no real downside to it, except that the file gets a little longer.

Add API changes to readme

Version 0.2 saw a lot of renames like liftMStreamF to arrM and MStreamF to MSF, these should be outlined in the readme.

Lists to MSFs in MaybeT to exceptions

In languages that distinguish between inductive and coinductive types, lists are inductive types, while the corresponding coinductive type is a "Stream that can end", i.e. an MStream Maybe. Consequently, there should be a map [a] -> MStream (MaybeT m) a (or even ListT m a -> MStream (MaybeT m) a for a correct implementation of ListT).

Maybe is a special case of an exception, and there should be a utility MSF (MaybeT m) a b -> MSF (ExceptT () m) a b.

Doc: Write tutorial application

There should be an easy tutorial that walks through the basic concepts and combinators. Here is an idea:

  • Concept: Write an app on dunai without bearriver that allows you to launch timers that will measure when your teas are ready.
  • Design: The app has two threads, connected through a wormhole.
    1. The first thread blocks on readLn and waits for the user to input new teas (data Tea = Tea { name :: String, duration :: Double }).
    2. The second thread collects the teas in a list, measures time and prints messages when a tea is ready.
  • Dunai technologies used:
    • Basic MSFs in IO
    • Wormholes
    • List monad? (multiple teas)
    • Exceptions? (messages when tea is ready)

I'm open for alternative suggestions, even of the form "I dare you to implement xyz in dunai"!

Add stack support

We should give stack users the possibility to build dunai with stack easily, and get dunai on stackage.

Create reverse frp zoo

It could live in examples, as an independent directory, with one cabal file with multiple applications/demos, and one or several markdown files explaining what each example is about.

Functor, Applicative and Num instances could be more general

Not so much a suggestion. Merely observing that:

{-# LANGUAGE FlexibleInstances #-}
import Control.Applicative
import Control.Arrow

instance Arrow a => Functor (a b) where
  fmap f = (>>^ f)

instance Arrow a => Applicative (a b) where
  pure x  = arr (const x)
  f <*> x = (f &&& x) >>^ (uncurry ($))

instance (Arrow a, Num c) => Num (a b c) where
  (+)         = liftA2 (+)
  (-)         = liftA2 (-)
  (*)         = liftA2 (*)
  abs         = fmap abs
  signum      = fmap signum
  negate      = fmap negate
  fromInteger = pure . fromInteger
  

I'm not sure whether there's any gain or loss in terms of performance. I suspect similar things could be done for VectorSpace, and possibly almost any arrow that produces values that are instances of a class.

Dependencies in BearRiver

Hi all,
BearRiver does not include Dependencies (random, deepSeq) that Yampa does.
It would be great if I could just swap Yampa with BearRiver in the cabal file without adding these dependencies too.
Instead a package BearRiverDepenencies could also be created, that just has dependencies on BearRiver, random & deepSeq

Use an external VectorSpace

Following the philosophy that dunai has to be slim, VectorSpace should really be a dependency. If there is no slim package supplying us with vector spaces, we should fork one.

This is not an API change or API addition, and its not urgent.

gcc error while trying to compiling dunai

I followed the steps outlined in the README but failed to compile dunai. I'm trying on a machine with macOS 10.11.6, ghc 8.0.1, cabal 1.24.0.0 and gcc "Apple LLVM version 8.0.0 (clang-800.0.42.1)". Oddly I was able to run the bouncing balls example (in examples/list) even though it uses dunai's MonadicStreamFunctions. Any idea what I'm doing wrong / what's broken?

$ cd dunai
$ cabal sandbox init
$ cabal install
Resolving dependencies...
Notice: installing into a sandbox located at
/Users/cech/Studium/GdI-Sem/dunai/.cabal-sandbox
Configuring transformers-compat-0.5.1.4...
Building transformers-compat-0.5.1.4...
Installed transformers-compat-0.5.1.4
Configuring transformers-base-0.4.4...
Building transformers-base-0.4.4...
Installed transformers-base-0.4.4
|
V
Configuring dunai-0.1.0.0...
Building dunai-0.1.0.0...
Failed to install dunai-0.1.0.0
Build log ( /Users/cech/Studium/GdI-Sem/dunai/.cabal-sandbox/logs/dunai-0.1.0.0.log ):
cabal: Entering directory '.'
Configuring dunai-0.1.0.0...
Building dunai-0.1.0.0...
Preprocessing library dunai-0.1.0.0...
clang: error: no such file or directory: 'dist/dist-sandbox-582313aa/build/Data/MonadicStreamFunction/Core.dyn_o'
`gcc' failed in phase `Linker'. (Exit code: 1)
cabal: Leaving directory '.'
cabal: Error: some packages failed to install:
dunai-0.1.0.0 failed during the building phase. The exception was:
ExitFailure 1

hiding swap in FRP.BearRiver

Hi all,
the swap function is exported from FRP.BearRiver but not from the original Yampa Package.
This could cause trouble with swap in Data.Tuple

Module Data.MonadicStreamFunction.Instances has unhelpful name

The module Data.MonadicStreamFunction.Instances has a name that suggests instances. Maybe class instances? Instead, it contains two functions that apply pointwise transformations.

Those should be somewhere else. This namespace would be useful for Arrow instances.

What is the purpose of Data.VectorSpace.Specific?

The module name of src/Data/VectorSpace/Specific.hs is weird. It does not really help. I would never intuitively go look for that there.

Do those instances belong somewhere else? Should the module be elsewhere?

Use a better ListT

The ListT implementation we're using (from transformers) is wrong (it's just m [a]) and we should eventually settle for a different, correct version.

Data.MonadicStreamFunction.sum is only defined for monoids

It should be defined for Num (or VectorSpace) as well in some way, otherwise one needs this annoying workaround all the time:

import Data.Monoid

mySumFrom :: (Num a, Monad m) => a -> MStreamF m a a
mySumFrom a = arr Sum >>> sumFrom (Sum a) >>> arr getSum

BearRiver broken when installing from Hackage

When adding bearriver in my cabal file and running 'cabal install' (its within a sandbox) then I get these errors:

Preprocessing library bearriver-0.10.4...
[1 of 8] Compiling FRP.Yampa.VectorSpace ( src/FRP/Yampa/VectorSpace.hs, dist/dist-sandbox-5cbfec19/build/FRP/Yampa/VectorSpace.o )
[2 of 8] Compiling FRP.Yampa.Vector3 ( src/FRP/Yampa/Vector3.hs, dist/dist-sandbox-5cbfec19/build/FRP/Yampa/Vector3.o )
[3 of 8] Compiling FRP.Yampa.Vector2 ( src/FRP/Yampa/Vector2.hs, dist/dist-sandbox-5cbfec19/build/FRP/Yampa/Vector2.o )
[4 of 8] Compiling FRP.Yampa.AffineSpace ( src/FRP/Yampa/AffineSpace.hs, dist/dist-sandbox-5cbfec19/build/FRP/Yampa/AffineSpace.o )
[5 of 8] Compiling FRP.Yampa.Point2 ( src/FRP/Yampa/Point2.hs, dist/dist-sandbox-5cbfec19/build/FRP/Yampa/Point2.o )
[6 of 8] Compiling FRP.Yampa.Point3 ( src/FRP/Yampa/Point3.hs, dist/dist-sandbox-5cbfec19/build/FRP/Yampa/Point3.o )
[7 of 8] Compiling FRP.BearRiver ( src/FRP/BearRiver.hs, dist/dist-sandbox-5cbfec19/build/FRP/BearRiver.o )

src/FRP/BearRiver.hs:18:1: error:
Failed to load interface for ‘Control.Monad.Trans.MStreamF’
Perhaps you meant
Control.Monad.Trans.MSF (from dunai-0.3.0.0)
Control.Monad.Trans.State (from transformers-0.5.2.0)
Control.Monad.Trans.MSF.Maybe (from dunai-0.3.0.0)
Use -v to see a list of the files searched for.

src/FRP/BearRiver.hs:24:1: error:
Failed to load interface for ‘Data.MonadicStreamFunction.ArrowLoop’
Perhaps you meant
Data.MonadicStreamFunction.Async (from dunai-0.3.0.0)
Data.MonadicStreamFunction.Core (from dunai-0.3.0.0)
Data.MonadicStreamFunction.Parallel (from dunai-0.3.0.0)

To reproduce:

  1. create new folder and cd into it
  2. run 'cabal init' (and follow all steps, create Main.hs)
  3. run 'cabal sandbox init'
  4. add 'bearriver' to dependencies in cabal file
  5. run 'cabal install'

Add github repo URL as Homepage in cabal file

The current cabal file does not include a home page.

Pointing people here would make it easier for them to find documentation, examples, etc.

This should be a one-liner, great for anyone who wants their first contribution :)

Reorg: Function naming

The nomenclature used for the API is not intuitive. Why are is there a function called arrM, another called arr and another liftS, when they all have similar signatures?

This needs to be improved.

The naming convention needs to be such that the entry barrier to entry is minimal. I'd rather use names related to signal processing than operational notions (step), but the latter may be unavoidable.

Reorg: Data.MonadicStreamFunction.Core

I'd like a reorganisation of Data.MonadicStreamFunction along the following principles:

  • Data.MonadicStreamFunction.Core implements only core features, to which I'd count:
    • MSF definition and its Arrow and Applicative instances
    • Lifting MSF along monad morphisms
    • Reactimation and embedding
    • Reexport of Control.Arrow (like Yampa core does)
  • Everything else is moved to Data.MonadicStreamFunction.Util or other places.
  • Modules like Control.Monad.Trans.MSF.* and Data.MonadicStreamFunction.Async only need to import core. They may use the MSF constructor.
  • Data.MonadicStreamFunction.Util implements utilities using core and possibly other modules. It doesn't need to use the MSF constructor.

Conflicting family instance declarations

When I make my own Vector type an instance of RModule and then want to use an operator cabal gives the following error message:
Conflicting family instance declarations:
Data.VectorSpace.Groundring a
-- Defined in Data.VectorSpace.Instances'
Data.VectorSpace.Groundring Vector
-- Defined in Robotics.ArDrone.NavDataTypes'

Document definitions using haddock

There are quite a few comments in the code that are discussion leftovers from research. There are also a lot of undocumented functions. I'd move the discussion-like comments into a separate text file and add haddock documentation for several functions.

Weaker reactimate signature in BearRiver

Hi all,
I would propose changing the signature from reactimate to the one used in the develop branch of the Yampa repo.
That would encurage people (like myself) that use Yampa from the devlop branch to switch to BearRiver

the new signature of reactimate would be:
reactimate :: Monad m a => (Bool -> m (DTime, Maybe a)) -> (Bool -> b -> m Bool) -> SF Identity a b -> m ()

bearriver: RandT and other transformers don't work directly

Disclaimer: I haven't tested this yet.

It seems to me that RandT is not usable yet the way we'd like it to use.

Typical dunai use case

myRandThing :: MSF (RandT g m) () a
myRandThing = _

myOtherRandThing :: MSF (RandT g m) a ()
myOtherRandThing = _

main = do
  g <- newStdGen
  reactimate $ evalRandS (myRandThing >>> myOtherRandThing) g

Problem in bearriver

This doesn't work in bearriver since an SF m a b is an MSF (ReaderT DTime m) a b, which means that the outermost monad is always a ReaderT. To remove the RandT layer, it must first be commuted past the ReaderT layer, i.e. one must define:

commute :: ReaderT r (RandT g m) a -> RandT g (ReaderT r m) a
commute = _

Then one needs to hoist an SF (RandT g m) a b along this monad morphism and then apply evalRandS, i.e.:

evalRandSF :: SF (RandT g m) a b -> g -> SF m a b
evalRandSF sf = evalRandS $ liftMSFPurer commute sf

Not sure whether the names are ok like this or should be improved.

Other monads

This is actually an issue for other transformers as well. We should maybe think about a more general solution, i.e. we've already axiomatised elsewhere what it means to be able to commute past a ReaderT layer.

Publish dunai - 0.4

In order for bearriver to compile directly from hackage, it needs features that are not in the current version of dunai. So, we need to publish also dunai as is, and include new changes in the future.

I believe this would have to be 0.4, if there were changes to the API (moves, deletions) since 0.3. I'd be happy to be proven wrong.

List of changes:

    * Adds support for random numbers using MonadRandom
      (thanks Jonathan Thaler -- @thalerjonathan).
    * Removes MSF constructor from many definitions
      (by Manuel Bärenz -- @turion).
    * Adds support for older GHC versions.
    * Moves some definitions/modules around.
    * dunai.cabal: Version bump (0.4).
    * examples/: Changes licenses, updates examples to use new API.

Warning: missing definitions in MSFExcept-related instances

With the current develop, the following warnings are shown:

src/Control/Monad/Trans/MSF/Except.hs:121:10: Warning:
    No explicit implementation for
      ‘fmap’
    In the instance declaration for ‘Functor (MSFExcept m a b)’

src/Control/Monad/Trans/MSF/Except.hs:123:10: Warning:
    No explicit implementation for
      ‘<*>’
    In the instance declaration for ‘Applicative (MSFExcept m a b)’

`bearriver`: definitions missing

BearRiver is missing some definitions available in Yampa. Ideally, and this is a big issue, it should include everything.

One should not worry at all about optimisations. Leaks and similar issues should be monitored and addressed systematically later.

Test where inlining will improve performance

In some places where functions are defined in terms of primitives (like accumulateWith and integral in terms of feedback), inlining might improve performance. This needs to be measured and implemented.

iPostKleisli and corresponding naming issue

We have iPost :: b -> MSF m a b -> MSF m a b which ignores the first input and outputs b instead. This can be generalised to iPostM :: m b -> MSF a b -> MSF a b (probably uncontroversial) and further to iPostKleisli :: (a -> m b) -> MSF a b -> MSF a b.

My question is whether...

  • this should be added to Data.MonadicStreamFunction as a fundamental building block,
  • or it should be implemented in a high-level way in terms of exceptions (potential efficiency issue).

Furthermore:

  • Should iPost be defined in terms of it (potential minor efficiency issue)?
  • What's a better name for it?
    • Note that it's a lot like (:) :: a -> [a] -> [a], so one might be tempted to write it like a list construction operator.

Formulate functions in Control.Monad.Trans.MSF.* without the MSF constructor

We should always strive to formulate most functions without the MSF constructor in order to find out which parts really need the constructor and whether our API is complete. A user of the library should never need to use the constructor.

Most modules below Control.Monad.Trans.MSF don't satisfy this ideal.

This doesn't change the API, and (if done right) not even functionality.

Test examples with travis

We should build all the examples with travis as well. As inspiration for a .travis.yml that works for several cabal packages in the same repository, have a look here.

Reorg: unify transformer lifting and running

@ivanperez-keera, we have a lot of different lifting and running functions around, do you have an opinion on what we should keep and what should be removed? I think we should go with one of the general approaches and reformulate (with inlining) everything in terms of it.

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.