[Haskell-cafe] Arrow laws of Netwire

Oleg Grenrus oleg.grenrus at iki.fi
Sun Feb 18 11:10:18 UTC 2018


As a side comment, it's fun how this is re-invented in similar-ish
contexts :)

E.g. `machines` [1]

newtype MealyT m a b = MealyT { runMealyT :: a -> m (b, MealyT m a b) }

or `arrows` (a = Kleisli m) [2]

newtype Automaton a b c = Automaton (a b (c, Automaton a b c))

[1]:
http://hackage.haskell.org/package/machines-0.6.3/docs/Data-Machine-MealyT.html
[2]:
http://hackage.haskell.org/package/arrows-0.4.4.1/docs/Control-Arrow-Transformer-Automaton.html


On 18.02.2018 11:17, Ivan Perez wrote:
> Hi
>
> > However, unless you have a strong reason to use arrowized FRP I
> would recommend that you go with one of the first-class FRP libraries. 
>
> TL;DR: Shameless self promotion ahead: we built an elementary library
> that seems to subsume many others, including AFRP and Classic FRP
> libraries, I'd like to know how it compares.
>
> Seeing what's just been said about netwire, I'd like to ask how these
> compare to each other. Among themselves, and also in relation to a
> separate construct that Manuel Bärenz and I built (note: I am the
> Yampa maintainer; Yampa is alive and well and more updates are coming
> your way :) ).
>
> In 2016 we published an article [1; mirror: 4] and a library [2] which
> aim at merging ideas in this field. I always thought they were pretty
> powerful, and so far I haven't found many limitations. (But I am
> biased, so maybe not the ideal judge.)
>
> It combines the CPS-based arrowized construct of Yampa with a monad,
> in a tiny definition:
>
> newtype MSF m a b = MSF { step :: a -> m (b, MSF m a b) }
>
> So, you provide one input sample and get, in a monadic context, an
> output and a continuation. Next time you provide the next input to the
> continuation, and so on.
>
> You can define stream as:
>
> type MStream m b = MSF m () b
>
> You can define sinks as:
>
> type MSink m a = MSF m a ()
>
> They have really cool properties [3], for instance, they are arrows,
> and if the monad is commutative then the arrow is commutative. We have
> instances for many other Arrow* classes.
>
> You can also define FRP on top of it, in the time-continuous sense, by
> using a Reader monad:
>
> type YampaSF a b = MSF (Reader Time) a b
>
> We have a version of Yampa defined on top of this that runs full (free
> and commercial) games just fine. It's API compatible (for what it
> implements).
>
> And, you can define classic FRP signals (and sinks, a-la reactive
> banana and, if paired, more similar to Daniel Winograd-Cort's work or
> Keera Hails):
>
> type Signal a = MStream Time a
>
> So you can use applicative style:
>
> s :: Signal Double
> s = -- predefined somewhere
>
> biggerS :: Signal Double
> biggerS = (* 100) <*> s
>
> You can do extremely cool things just by altering the monad:
> - If the monad is Maybe, they terminate because there may not be a
> continuation (and an output).
> - If the monad is Either, they terminate with a result. This is the
> basis for switching, which we get "for free".
> - If the monad is [], they spawn. This implements parallelism with
> broadcasting for free.
> - You can use a Writer monad and some smart tricks to do continuous
> collision detection.
> - You can use state if to avoid the bottleneck issue that people
> criticise AFRP for.
> - You can use transformers to stack these effects.
> - You can also use IO as your monad, if you want to access mouse
> position and other external stuff, print a log, or sink directly from
> your network.
>
> So far, I've found that we can pretty much do anything we want with
> this. It's simple to use, classic or arrowized at will (you can
> combine the two). I'm investigating performance, which for the games
> I've tried is really good and gives us flat and low memory profiles,
> and I believe we can do some pretty smart things with GADTS and
> re-writes to make things as fast as they can theoretically be.
>
> How does this compare to other FRP and F;RP libraries around?
>
> Cheers
>
> Ivan
>
> PS. For whoever is interested, there's the FRP zoo on github that
> shows the same example in multiple variants.
>
> [1] https://dl.acm.org/citation.cfm?id=2976010
> [2] https://hackage.haskell.org/package/dunai
> [3] http://www.cs.nott.ac.uk/~psxip1/papers/msfmathprops.pdf
> <http://www.cs.nott.ac.uk/%7Epsxip1/papers/msfmathprops.pdf>
> [4]
> http://www.cs.nott.ac.uk/~psxip1/papers/2016-HaskellSymposium-Perez-Barenz-Nilsson-FRPRefactored-short.pdf
> <http://www.cs.nott.ac.uk/%7Epsxip1/papers/2016-HaskellSymposium-Perez-Barenz-Nilsson-FRPRefactored-short.pdf>
>
> On 17 February 2018 at 11:43, Ertugrul Söylemez <esz at posteo.de
> <mailto:esz at posteo.de>> wrote:
>
>     Hi,
>
>     >         -- I almost sure this is correct, since it is copied
>     >         -- from "Programming with Arrows", J. Hughes
>     >       mapA :: (ArrowChoice a) => a b c -> a [b] [c]
>     >       mapA f = proc input ->
>     >         case input of
>     >           [] -> returnA -< []
>     >           z:zs -> do y_ <- f -< z
>     >                      ys_ <- mapA f -< zs
>     >                      returnA -< y_:ys_
>
>     Yes, this is correct.  However, the ArrowChoice instance in
>     Netwire has
>     always been questionable.  The correct (and much more efficient)
>     way to
>     implement mapA is as a primitive combinator much like the parallel
>     switches in Yampa.
>
>     The Netwire implementation and API has been more focussed on providing
>     features over reasonable semantics, and that eventually led me to
>     abandon it in favour of a more minimalistic library that is easier to
>     reason about (wires).  Please consider Netwire deprecated and I
>     recommend you don't use it for new applications, if possible.  I'm
>     still
>     open to reviewing and merging code contributions to support legacy
>     applications, but other than that I would much prefer to just let it
>     become a piece of AFRP history. =)
>
>     If you must use AFRP, I recommend either my new library called
>     wires, or
>     the progenitor of all, Yampa.  However, unless you have a strong
>     reason
>     to use arrowized FRP I would recommend that you go with one of the
>     first-class FRP libraries.  I currently recommend either:
>
>       * reactive-banana: very simple and easy to learn API, plus the
>     author
>         runs a blog with lots of information on FRP.  This is the
>     library I
>         recommend to FRP beginners.  Or
>
>       * reflex: my personal favourite, more focussed on practical concerns
>         and efficiency, a more versatile API that easily integrates with
>         applications with a "main loop", such as real-time games.  The
>         trade-off is far less documentation and a more complicated API.
>
>     Sorry for not directly addressing your question, but I hope I
>     convinced
>     you to just switch to a different library. =)
>
>
>     Greets
>     ertes
>
>     _______________________________________________
>     Haskell-Cafe mailing list
>     To (un)subscribe, modify options or view archives go to:
>     http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>     <http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe>
>     Only members subscribed via the mailman list are allowed to post.
>
>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.




More information about the Haskell-Cafe mailing list