ivanperez-keera / dunai Goto Github PK
View Code? Open in Web Editor NEWClassic FRP, Arrowized FRP, Reactive Programming, and Stream Programming, all via Monadic Stream Functions
Classic FRP, Arrowized FRP, Reactive Programming, and Stream Programming, all via Monadic Stream Functions
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.
They're all special cases of accumulateWith
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.
Any reason why this might be worse?
listToMaybeS = foldr iPost exit
Instead of:
listToMaybeS [] = exit
listToMaybeS (b : bs) = iPost b $ listToMaybeS bs
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?
You probably already know about them but since you explicitly invite "issues" like this, you could check out varying
and auto
. Perhaps you could add a comparison to the readme.
Or you could even try to merge your emphasis on the monad transformer aspect into varying
on github.
Since the API has changed, bearriver.cabal and the other examples etc. need updating. (As a courtesy, this could also be done for some other dunai-dependent projects I know about, like https://github.com/mkm0815/NXTgeneration or https://github.com/tmh2211/hs-drone)
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...
Data.MonadicStreamFunction
as a fundamental building block,Furthermore:
iPost
be defined in terms of it (potential minor efficiency issue)?(:) :: a -> [a] -> [a]
, so one might be tempted to write it like a list construction operator.The MSF constructor should only be used in some core modules in dunai, not anywhere else (also not in bearriver).
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.
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.
Consider putting all examples under GPL or similar.
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
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.
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.
In order to document changes from the paper, we could include one example that lists them all, with references to the locations in the paper, and their updated implementations.
This issue replaces #14.
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.
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
@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.
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.
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.
In order to simplify our lives, we could make travis automatically publish stable versions of packages on hackage. A new user has been created for this ( #59 ).
Example of how to do this is are in https://github.com/ivanperez-keera/Yampa/blob/develop/.travis.yml#L31-L38, and https://github.com/keera-studios/keera-hails/blob/master/.travis.yml#L86-L109.
The issue is due to missing type class constraints that were needed prior to GHC 7.10.
It just needs additional Functor constraints in some places.
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:
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
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'
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.
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:
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.Num
etc. until they explicitly import the corresponding submodule.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.
We should give stack users the possibility to build dunai with stack easily, and get dunai on stackage.
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)’
In order to connect to existing code, we should have instances for ArrowReader
etc. from https://hackage.haskell.org/package/arrows
This would also make certain constructions easier, since one often has several transformers in the monad stack, and arrows
has type classes like mtl
does.
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.
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
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.
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.
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
instancesMSF
along monad morphismsControl.Arrow
(like Yampa core does)Data.MonadicStreamFunction.Util
or other places.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.There should be an easy tutorial that walks through the basic concepts and combinators. Here is an idea:
readLn
and waits for the user to input new teas (data Tea = Tea { name :: String, duration :: Double }
).MSF
s in IOI'm open for alternative suggestions, even of the form "I dare you to implement xyz in dunai"!
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.
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.
myRandThing :: MSF (RandT g m) () a
myRandThing = _
myOtherRandThing :: MSF (RandT g m) a ()
myOtherRandThing = _
main = do
g <- newStdGen
reactimate $ evalRandS (myRandThing >>> myOtherRandThing) g
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.
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.
Hi all,
SF is not exported from FRP.Yampa in BearRiver.
So no Yampa source will compile with BearRiver
Version 0.2 saw a lot of renames like liftMStreamF
to arrM
and MStreamF
to MSF
, these should be outlined in the readme.
CHANGELOG's missing.
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
.
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 :)
Please, @chriz-keera, could you create a new hackage user for this project?
We need to find out which seq
s and bangs actually improve efficiency, and add them systematically.
This would be a two-line patch, probably.
An example is here:
https://github.com/ivanperez-keera/Yampa/blob/develop/Yampa.cabal#L37-L47
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 ()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.