[HN Gopher] Functional Reactive Programming
       ___________________________________________________________________
        
       Functional Reactive Programming
        
       Author : amelius
       Score  : 171 points
       Date   : 2022-08-13 11:18 UTC (3 days ago)
        
 (HTM) web link (wiki.haskell.org)
 (TXT) w3m dump (wiki.haskell.org)
        
       | dllthomas wrote:
       | There's a lot of talk of Rx libs, but from
       | https://reactivex.io/intro.html I see:
       | 
       |  _" It is sometimes called "functional reactive programming" but
       | this is a misnomer. ReactiveX may be functional, and it may be
       | reactive, but "functional reactive programming" is a different
       | animal. One main point of difference is that functional reactive
       | programming operates on values that change continuously over
       | time, while ReactiveX operates on discrete values that are
       | emitted over time."_
       | 
       | At the same time, I see lots of references to FRP on
       | https://reactivex.io/tutorials.html so I am not sure what the
       | actual position of the project is, or the actual status of the
       | technologies (maybe things have changed?).
        
         | Paradigma11 wrote:
         | There was reactive programming coming from c#. You can look up
         | Eric Meijer and the duality of Observable and IEnumerable. It
         | is discrete, push and event based and has some history with
         | flow based programming.
         | 
         | FRP comes from Conal Elliot and has a continuous pull based
         | aspect with maybe an additional reactive event based component
         | on the side.
         | 
         | Then the javascript horde discovered rx and since functional
         | programming is cool, rp is now frp.
        
           | dllthomas wrote:
           | But an article on FRP on haskell.org is probably actually
           | about FRP, right?
        
             | Paradigma11 wrote:
             | Indeed. That is why you have: at : Behavior a - Time - a
             | which is a pull based continuous data type. This is a very
             | elegant concept but comes with its own set of difficulties
             | if implemented naively (space and time leaks).
             | 
             | A similar concept is shown here:
             | https://www.microsoft.com/en-
             | us/research/uploads/prod/2000/0...
             | 
             | Imo the main problem in the end is/was that not many
             | problems are that conveniently described as continuous.
             | Discrete and push based (rx) can do most things and even
             | that is overused. It makes problems that are otherwise very
             | hard, much easier to describe and solve using the many
             | powerful combinators https://www.learnrxjs.io/learn-
             | rxjs/operators
             | 
             | On the other hand you make all those easy problems quite a
             | bit harder and if you are not disciplined you end up with
             | complex rx "queries" that have semantics that you dont
             | understand.
        
       | BoumTAC wrote:
       | I learn FP throught ELM and I really enjoyed it. Unfortunately
       | the language seems dead.
       | 
       | What are the easiest FP language to learn ? I checked multiple
       | time Haskell but it seems really hard
        
         | macintux wrote:
         | Very different from Elm or Haskell, but Erlang was my gateway
         | drug to FP. I'd tried and failed to learn Lisp on a few
         | occasions.
         | 
         | Elixir is more popular these days, but I still prefer Erlang's
         | syntax. Minimalistic, helps me "think" Erlang instead of
         | imperative/OO.
        
         | miggol wrote:
         | So sad to hear that Elm appears to be dead. It really excited
         | me at first but I guess that like many I never made the time to
         | give Elm a serious attempt.
         | 
         | For me, learning Racket was not too hard. The offical learning
         | materials are excellent, although they are also meant for
         | programmers starting from zero. For me that meant that I
         | occasionally skipped over parts I considered "too easy" only to
         | be confronted by my hubris later.
         | 
         | For me, what makes lisps easier than Haskells is that lisps are
         | multi-paradigm. So you can write a more imperative
         | implementation of whatever you're doing right next to the
         | "proper" functional one to get things to click, and also to
         | identify those elusive merits of functional programming.
         | 
         | I wouldn't describe the Racket community as "vibrantly alive",
         | but it's definitely still moving along. And the knowledge is
         | very transferrable to other lisps and schemes. Next on my list
         | is Carp, for example. And if you (choose to) use Emacs you'll
         | reap even more rewards from the knowledge transfer.
        
           | carapace wrote:
           | Elm isn't dead. It's in that happy place of stability, people
           | are getting things done with it w/o hassle or churn.
           | 
           | I've heard that an Elm-to-native app compiler is in the works
           | somewhere, which IMO is very exciting.
        
           | Akronymus wrote:
           | Maybe elmish could be of interest to you?
           | https://github.com/elmish/elmish
        
         | immigrantheart wrote:
         | OCaml fits the bill for me. It is an amazing language, very
         | practical, fast, and easy to code with. It is a shame that I
         | didn't discover OCaml sooner.
         | 
         | FWIW, I tried Elm, Haskell, PureScript, Elixir.
        
           | tasuki wrote:
           | What were some drawbacks of PureScript, or why do you prefer
           | OCaml? I've only ever used Elm and Haskell, but been eyeing
           | PureScript recently...
        
         | swyx wrote:
         | what makes you say Elm is dead?
        
         | sfusato wrote:
         | Elixir paved the way into FP for me. I did Lisp, Prolog and a
         | bit of Java & Javascript done the FP way (I know) at University
         | though, but only with Elixir I've had the "now I get it" Eureka
         | moment.
        
         | cardanome wrote:
         | Elm is not dead. It just prefers a slow release schedule but is
         | still actively worked on in the background.
         | 
         | That said, you might want to check out OCaml for general
         | purpose programming. Super fast compiler, great performance,
         | can target both native and JS.
         | 
         | It is easier to use than Haskell due to defaulting to eager
         | evaluation (like most languages) strategy instead of laziness
         | and being generally more pragmatic, offering more escape
         | hatches into the imperative world if need be. Plus great upward
         | trajectory with lot's of cool stuff like an effects system and
         | multi-core support coming.
         | 
         | Real World Ocaml is a decent resource:
         | https://dev.realworldocaml.org/
        
           | jamil7 wrote:
           | > you might want to check out OCaml for general purpose
           | programming
           | 
           | Any tips on backend frameworks to look at? I need to write a
           | small websocket service for a side-project and have always
           | wanted to try OCaml. I came across
           | https://github.com/aantron/dream.
        
             | phosphorco wrote:
             | You'll have a much easier time doing business stuff with F#
             | - it's OCAML inspired but has access to broader .NET
             | ecosystem. We're using it on front end as well w/ Fable
             | compiler. It's pretty awesome.
        
             | pkilgore wrote:
             | Dream is great for small http services -- I've not used the
             | websocket support so I can't say much about it.
             | 
             | I do highly recommend starting with one of the Dream
             | example projects just to lower the barrier to entry on the
             | tooling side.
             | 
             | You can also use Rescript (compiles to very readable
             | Javascript), which is the OCaml type system with more
             | familiar syntax and some of the complexity shaved off.
        
         | airza wrote:
         | I have been using rxjs with typescript for some stuff.
         | Functional reactive has proven to be a good paradigm for some
         | stuff in the UI and thornier parts of shared state across
         | multiple applications.
        
         | valenterry wrote:
         | Proper FP as in pure functional programming?
         | 
         | Probably Purescript in the frontend (also hard) or Scala on the
         | backend (easier, because you can also write impure code).
        
         | smcl wrote:
         | F# might be a good shout.
        
           | quickthrower2 wrote:
           | There is the SAFE stack https://safe-
           | stack.github.io/docs/overview/ where the E means Elmish
        
         | rstarast wrote:
         | I have high hopes for the young Gren fork of Elm https://gren-
         | lang.org/.
        
           | brabel wrote:
           | It was pretty obvious that at some point, someone would fork
           | Elm, given how Elm has always preferred purity over
           | practicality... but it's not clear how this fork improves
           | things even after reading the (tiny) documentation... can you
           | expand on that?
        
             | yakshaving_jgt wrote:
             | > Elm has always preferred purity over practicality
             | 
             | Elm preferring purity _is_ its practicality.
        
             | rstarast wrote:
             | It seems to address the important problems with Elm, around
             | its overly restrictive project management, by 1.
             | introducing more flexible package management (e.g. you can
             | depend on a fork of a core package, or a private git repo
             | etc.) 2. being open to adding various missing web APIs
             | (e.g. while I'm not sure it's there yet, I expect
             | websockets to make a return, which were dropped with Elm
             | 0.19) 3. generally going for an open development model
             | (even just not having to wait years to fix trivial
             | crippling bugs in the compiler is a step forward...).
             | 
             | The other part is that I have a good impression of the
             | person/people behind it and could see it sticking, for
             | whatever that's worth.
        
         | cosmic_quanta wrote:
         | 'Haskell Programming from First Principles' is a great book
         | which helped me a lot in the beginning.
        
         | wyager wrote:
         | Haskell is sort of the base model option if you want real full-
         | power FP, and not just support for some FP techniques.
        
         | giovannibonetti wrote:
         | Elm started with FRP and moved on to Model-View-Update, which I
         | agree is way simpler to understand and work with.
         | 
         | https://elm-lang.org/news/farewell-to-frp
        
         | rkangel wrote:
         | I would recommend starting with Elixir. Elixir is a _dynamic_
         | functional language, unlike Haskell /Ocaml etc. which are
         | statically compiled languages.
         | 
         | This means that you can learnt he basic concepts of operating
         | on data with pure functions, pattern matching etc. Plus it's a
         | nice language that is great for building a lot of things
         | (Phoenix is a great web framework).
         | 
         | Once you've got some of that background of how you build
         | functional programs rather than OO, moving to something like
         | Haskell or Ocaml is a bit easier because it becomes more about
         | understanding how to declare types to keep the compiler happy
         | and less about the fundamental program design stuff.
        
       | aporetics wrote:
       | For those of you interested in hearing the inventor of FRP talk
       | about it, take a look at Conal Elliott's retrospective talk in
       | 2015:
       | 
       | https://youtu.be/j3Q32brCUAI
       | 
       | Especially useful for those whose only exposure to FRP is through
       | frp-inspired libraries (they're not the same thing).
        
         | 725686 wrote:
         | This might be interesting from a CS perspective, but useless to
         | developers who have to create real life messy business
         | applications.
        
           | aporetics wrote:
           | As a developer of real life messy code (as opposed to unreal
           | life?), I have never found ignoring CS to be beneficial; and
           | on the other hand, deciding in advance that CS is not helpful
           | is hubristic: you never know when theoretical insight will
           | become actionable.
           | 
           | On the other hand, who wouldn't be curious? Like someone who
           | purports to enjoy fast cars but has no interest in
           | understanding internal combustion or electric engines?
        
       | dfee wrote:
       | Is it viable to build a traditional web product/company on top of
       | Haskell?
       | 
       | That sounds like a silly question - but I'm serious. I'm enamored
       | by the beauty of FP, but I'm not sure if there's enough tooling
       | or libraries to get to market.
       | 
       | For example - GraphQL. There are two packages (mu and morpheus),
       | but neither clearly document their feature parity in relation to
       | other packages for other languages - and things like dataloaders.
       | 
       | The Reddit almost encourages people to use a different language,
       | too.
        
         | _query wrote:
         | Yes, it's possible to build a traditional web company with
         | Haskell. We've made IHP exactly for that :) It's like
         | Rails/Django but for Haskell. https://ihp.digitallyinduced.com/
         | We specifically try to be batteries-includes (like rails), so
         | you don't have to think too much about what libraries to use,
         | the core of IHP can get you very far without needing to
         | manually decide between libraries.
         | 
         | IHP even won a G2 badge, which is kind of funny and ironic for
         | a Haskell project :D https://www.g2.com/products/ihp/reviews
        
         | hiptobecubic wrote:
         | I have never tried, but my impression is basically "You could,
         | but why would you?" Haskell had a big jump in popularity around
         | a decade ago, but it didn't gain traction with the "i'll grind
         | 17 hours a day to become a rockstar ninja whatever" demographic
         | that every language seems to bootstrap itself off of. I won't
         | speculate as to why, but the end result is that Haskell is
         | missing a lot of "adapter"-style libraries and instead is just
         | a bunch of building blocks. Yeah you can write great stuff in
         | Haskell, but also you have no choice. No one else has written
         | what you need so you'll be writing it yourself.
         | 
         | The benefits of Haskell don't even _really_ seem that useful
         | when you're just writing yet another big ass crud app where the
         | main goal is to convert json into some other json and then
         | maybe render it. I could see it making more sense in specific
         | domains where the main challenge is wrangling a complex mess of
         | business logic into something you can be confident about. Not
         | like "is my shopping cart correct" but "how can I optimize this
         | PCB design to reduce trace length and total area?"
        
           | yakshaving_jgt wrote:
           | > The benefits of Haskell don't even _really_ seem that
           | useful when you're just writing yet another big ass crud app
           | where the main goal is to convert json into some other json
           | and then maybe render it.
           | 
           | The benefits have been massive for me, and I'm often doing
           | basically this.
           | 
           | Maybe you should just try it?
        
         | JoelMcCracken wrote:
         | You absolutely can. Its a great platform for this.
         | 
         | There may not be as wide a variety of libraries as you would
         | hope, but that's true of any smaller language.
         | 
         | The main thing you need to be able to do is have the wisdom to
         | avoid the footguns. They're quite different from the footguns
         | in other languages. in general, using Haskell well requires a
         | good bit of experience with it, and knowledge of who in the
         | community are selling false solutions.
        
         | mdcds wrote:
         | In 2015-2016 SF Haskell meetup used to be hosted by an ed-tech
         | company that used Haskell as the main language, so maybe
         | viable.
        
         | yakshaving_jgt wrote:
         | > Is it viable to build a traditional web product/company on
         | top of Haskell?
         | 
         | Yes. I've been doing it for years. I also employ several
         | Haskell developers.
         | 
         | We're happy.
         | 
         | > I'm not sure if there's enough tooling or libraries to get to
         | market.
         | 
         | There are.
        
       | endgame wrote:
       | FRP is a fascinating paradigm, but I find I really have to turn
       | my brain inside-out to "get" it. But it's really cool to have UIs
       | that are completely consistent.
        
         | mpweiher wrote:
         | The funny thing is that good ole MVC also gave us UIs that are
         | completely consistent.
        
           | valenterry wrote:
           | Not really. It's just that at the time, SPAs and concurrent
           | requests were not really a thing or only used rarely.
        
             | mpweiher wrote:
             | Yeah, actually really.
             | 
             |  _Actual_ MVC has the model notifying the UI that it has
             | changed and then the UI updating itself from the model, by
             | pulling data. That 's always consistent.
             | 
             | We then did all sorts of things that we _call_ MVC, but
             | that do not follow the MVC-defined interaction patterns at
             | all, particularly either the model or other views
             | incrementally poking data into the view.
             | 
             |  _That_ doesn 't work, and it is nigh impossible to keep
             | consistent. It also isn't MVC.
             | 
             | I haven't written this up stand-alone, but I talk about it
             | a little here:
             | https://blog.metaobject.com/2022/06/blackbird-simple-
             | referen...
        
               | valenterry wrote:
               | So, what if you have a background process (running in the
               | controller I assume) that updates data in the model
               | periodically from somewhere. And at the same time you
               | have the user making changes to the model. How is
               | consistency guaranteed here by having "UI updating itself
               | from the model, by pulling data"?
               | 
               | Maybe I have a different understanding of "consistency"
               | but this might very well lead to undesired results if the
               | logic of data updates isn't well-controlled. The
               | developer needs to decide if the updates can happen
               | arbitrarily or if some kind of transaction-model needs to
               | be used, forcing the background process to wait during
               | user interactions or the other way around, etc.
               | 
               | I don't see how MVC solves that problem.
        
               | mpweiher wrote:
               | This is not MVC's problem to solve. It also doesn't solve
               | global warming.
               | 
               | If you have unprotected multithreaded imperative updates
               | of global data, _nothing_ is consistent. Has nothing to
               | do with MVC or no MVC.
               | 
               | Actually having a consistent state to present to the UI
               | is the model's problem.
               | 
               | Oh, and for goodness sake, don't have any kind of async
               | update process running in the controller. All this stuff
               | belongs in the model.
               | 
               | If you're doing that sort of stuff in the controller, I
               | can see why you're having problems with concurrency.
               | You're also almost certainly not doing MVC.
        
               | valenterry wrote:
               | > If you have unprotected multithreaded imperative
               | updates of global data, nothing is consistent.
               | 
               | Yeah, but that is exactly what FRP solves (or strives to
               | solve) and MVC does not give you on it's own (as you
               | said). Ofc MVC can be used in combination with other
               | techniques to gain consistency, but it doesn't provide it
               | on its own, which is what I believe was implied by your
               | original post.
               | 
               | If you were just talking about the UI in isolation, then
               | yeah, maybe MVC gives you that, but it misses the point
               | of what FRP gives you.
        
               | mpweiher wrote:
               | > If you were just talking about the UI in isolation
               | 
               | Comment I was replying to:
               | 
               | >> But it's really cool to have UIs that are completely
               | consistent.
               | 
               | So yes, we kinda were talking about the UI, keeping that
               | consistent (with the model, presumably). Hence MVC.
               | 
               | Keeping the model consistent is another topic.
        
               | valenterry wrote:
               | I see - I guess the OP had something different in mind
               | when they meant UI, not just the pure View. But point
               | taken, I understand your response.
        
             | cybrox wrote:
             | You can build perfectly fine SPAs using an MVC
             | architecture, even with lots of concurrent requests and
             | data fetching. This is why JS has an event loop and why we
             | invented data-binding.
        
               | wiseowise wrote:
               | You can build perfectly fine SPAs in one big file, what's
               | your point?
        
           | klysm wrote:
           | Yeah but for a limited subset of desirable functionality. It
           | sucks to use for something where you want a dynamic UI.
        
             | mola wrote:
             | Can you elaborate? An example for a feature which would be
             | a real pain in MVC but easypeasy with FRP?
        
               | klysm wrote:
               | I'm not saying FRP makes anything easy, just that there's
               | a set of things that are desirable that MVC makes
               | difficult. Right now I'm making a graphical node editor
               | with a lot of drag and drop that displays live data
               | streams. I can go into more detail about why a typical
               | MVC sucks for this but it definitely does.
        
           | daxvena wrote:
           | Another funny thing is that good ole vacuum tube computers
           | could automate computation before transistors became
           | widespread.
        
           | valcron1000 wrote:
           | I disagree. The moment my controller needs to "set" or
           | "update" something in the model the whole thing becomes a
           | mess in my experience. FRP requires that you change the way
           | you code but it's 100% worth IMO.
        
             | mpweiher wrote:
             | Well, you can let the view do this and things get better
             | ;-)
        
       | cybrox wrote:
       | As someone who had to maintain two applications written entirely
       | using the FRP Paradigm (Rx in Kotlin/Swift with a heavy focus on
       | FRP principles), I am fascinated the idea but I absolutely hated
       | the experience.
       | 
       | Writing behaviour flows can end in beautiful blocks of easy to
       | understand operations. However, as these get more complex and you
       | need to combine multiple data streams, logic is scattered all
       | over a module.
       | 
       | Refactoring data-flows that go through multiple modules is a huge
       | hassle. Sometimes, we would spend hours just refactoring data-
       | passing, wrapping and unwrapping and tests surrounding modules,
       | because we needed to pass some additional values.
       | 
       | It doesn't help that you have to set up all behaviours at setup
       | time, which means the code is mixed with one-time setup code
       | which regularly confused people working on the projects as to
       | what is run at startup time and what is run per-event.
       | 
       | Debugging itself was mostly hampered by the libraries that we
       | used not providing adequate tools for the job but even if they
       | did, it was a lot more difficult to reason about compared to
       | something like async/await based code or callback chains.
       | 
       | I can imagine FRP works better in purely functional languages but
       | implementing FRP paradigms in general purpose languages -
       | especially when interfacing with non-functional code, which is
       | often necessary - has led to nothing but trouble for me.
        
         | 62951413 wrote:
         | That's basically my Akka (akka-streams/Alpakka specifically)
         | experience. When it works it's great and terse. If it
         | occasionally hangs in the middle of things good luck finding
         | that one timeout parameter you need to adjust. Also, not all
         | people who actually use Actors bother to draw a large FSM
         | diagram.
        
         | zmgsabst wrote:
         | Do you have any thoughts on what would make a better
         | experience?
        
           | jfoutz wrote:
           | So, I'll start with a disclaimer - I've only futzed around
           | with FRP in Haskell, and never for money. Somewhere on an old
           | computer I've got some code to simulate a pool table. But it
           | has been a few years.
           | 
           | The pool table is pretty fun to model. You've got events,
           | which are collisions, and you've got an evolving state that
           | you can sort of fast-forward through thanks to elementary
           | physics. if you want to sample at a given time, you can. You
           | can calculate out the time to the next event (collision with
           | another ball or bumper)
           | 
           | For me, when I got to multiple objects interacting at
           | different times it got really tough to store the state of the
           | world. (like after the break) I didn't try to support angular
           | momentum - but it would have been fairly straightforward to
           | add.
           | 
           | What I've been thinking about lately, is algebra driven
           | design https://algebradriven.design That'd really help with
           | nailing down the data structures and operations on them. That
           | book has a couple of really gnarly sequenced state with
           | constraints examples, that came from real production code.
           | 
           | There's no closed form solution to some problems (a lot! most
           | problems!). So I think really nailing down a data structure,
           | and providing operations on that data structure are
           | essential. You, well, I need to create an environment where I
           | can create tactics for solving special cases, without that
           | code for the tactic getting smeared all over the code base.
           | 
           | I'm a dilettante, I've got very little experience on the JS
           | side of things. But from pure Haskell, I'm a reasonably
           | sophisticated amateur. So take my opinion in that context.
           | 
           | I think the automated tooling for finding laws presented by
           | Sandy Maguire really have a lot of potential for Locking down
           | those interactions - and opening up new ways of decomposing
           | those interactions, to make more sophisticated descriptions
           | of interactions. I'm not clever enough to find a closed form,
           | but given some state and a time delta, I can work out a bunch
           | of special cases - the interactions. Keeping that tidy is
           | tricky. That algebra approach seems really promising.
           | 
           | Again. I'm a dilettante. Take my opinion in that context.
           | There are probably horrible corners where all this falls
           | down. Anyway, the day is starting and it's almost time to go
           | wrestle yaml.
        
             | mncharity wrote:
             | Having a state algebra can also help with speculative
             | execution, as when doing FRP-like complex event processing
             | on human input device streams, while preserving
             | responsiveness despite diverse latencies.
             | 
             | Consider doubleclick. After a click, rather than pausing
             | for 30 frames to see if a second click eventually shows up,
             | you can act immediately, and if there's later a second
             | click, retract and rerun with a doubleclick event.
             | 
             | With incremental speech recognition, interpretation of past
             | words can change as a sentence progresses, so "Launch the
             | missiles!" can replay as "Lunch is mussels! In butter!".
             | 
             | Keyboard and ml-based visual tracking have very different
             | latencies. So when combining them (eg, which finger pressed
             | the key, where on the keycap, and what were any other
             | vision-derived key modifiers), you can pursue a guessed-at
             | transition immediately, and then correct if needed when
             | tracking finally coughs up the hand pose.
             | 
             | Edit: Hmm. Well... having "retractable state transitions".
             | "Algebra" has other implications. Edit edit:
             | s/reversible/retractable/ - sorry.
        
               | jfoutz wrote:
               | Yeah. Java swing early on actually paused the event loop
               | waiting for a second mouse click to return a double
               | click. If I recall, some platforms would drop those
               | events while paused, others would queue them. I think X
               | dropped, windows didn't. this caused some workarounds
               | smeared across the codebase.
               | 
               | It's never going to be easy, and somebody has to pick the
               | "right" answer. With more structure, you can get more
               | consistency. I may not like the answers, but they're
               | consistent answers and so I can reason about them.
               | 
               | Reversible state transitions is a whole other bag of
               | mixed metaphors. But I'd still say, more structure makes
               | it consistent, and then you can reason about it, and then
               | you can maybe solve some of those cases.
        
         | amarant wrote:
         | Huh, my experience with Rx-Java is (partially) the opposite to
         | yours. Partially because I've seen it used poorly in one
         | project, and it was quite horrible, but that time it was more
         | due to misusage of RX than it was the fault of RX itself.
         | 
         | The second time I've used it in a big commercial project it was
         | used well, and that remains the best codebase I've ever worked
         | with. Super easy to reason about, extremely performant, easily
         | the cleanest asynchronous codebase I've ever seen.
         | 
         | I do believe surrounding tooling is important though. Part of
         | why that codebase was so clean was because it used a framework
         | that integrates very well with RX-Java (micronaut).
         | 
         | That said, I've never worked with await/async in any larger
         | project, so I can't really compare the two fairly.
        
           | cybrox wrote:
           | I agree that the surrounding framework (and I'd like to add
           | also additional libraries) have a huge impact on this
           | experience.
           | 
           | The codebase I have worked on might be a bit of an edge-case
           | too, as it was used in realtime audio/video communication, so
           | ms-timing, order of async operations and keeping a consistent
           | state were absolutely necessary.
           | 
           | Using Rx for such complex, long-lived business logic is
           | probably a long shot from using it for a cleanly structured
           | SPA for example. I've used a lot of reactive concepts in
           | applications that simply fetched and displayed data and in
           | those cases, I really enjoyed it.
        
           | twawaaay wrote:
           | I am big fan of FRP with Java and RxJava/Reactor. When I
           | learned about it three years ago I practically got drunk on
           | it.
           | 
           | I think the issue is, the more power you get the more you
           | have to be vigilant and more effort into ensuring the power
           | is used wisely. The first project I joined that used RxJava
           | learned this lesson very painfully.
           | 
           | In my projects I am ensuring some standards on how APIs are
           | constructed and expected to behave so that composing large
           | reactive systems is not getting out of hand very quickly.
           | 
           | Another problem is the steep learning curve for people who
           | learned to mostly copy/paste code from Stack*. You can create
           | very quickly what would normally be a very complex
           | application with just few lines of code of Reactor, but it is
           | not for free -- you still have to understand what it all does
           | and how it all works or you will face consequences at some
           | point.
        
         | disantlor wrote:
         | i've been writing FRP code in JS for years now. Ease of
         | refactoring and total clarity of what is happening (assuming
         | you are familiar with the FP methods, etc) are the biggest
         | advantages.
         | 
         | I agree the code can balloon in size, and gets a bit hard to
         | organize at some point, but the self-documenting aspect of it
         | is amazing.
         | 
         | I combine an FRP framework (bacon.js) with Ramda.
         | 
         | I'll admit I've had trouble working with things like React
         | because I'm so used to wiring everything up explicitly and
         | there being no "magic" behavior.
         | 
         | The explicitness is probably what makes it seem so unwieldy as
         | the code/team scales
        
           | cybrox wrote:
           | Out of curiosity, a lot of people are praising the "self-
           | documenting aspect of [Reactive Code]", and I definitely see
           | why.
           | 
           | A single block of statements that transform and handle data
           | in a specific way is indeed almost self documenting, which is
           | really cool.
           | 
           | However, how did this work for you with more complex
           | combinations and transformations?
           | 
           | For example, our codebase had one module that took inputs
           | from multiple different sources (low-level network handling
           | based on a library) and generated a consistent state out of
           | them. To keep the code performant, we introduced some
           | intermediary values, so that certain transformations had to
           | be run less frequent. (this was necessary)
           | 
           | In the end, we ended up with a ~500LoC module. I wrote the
           | same later with async/await and split everything into ~20
           | functions, which worked really well. The reactive version
           | however, was just a bunch (~15) blocks of transformations,
           | which were somewhat self explanatory in themselves but it was
           | almost impossible to trace the flow of data through the whole
           | module without drawing it up.
           | 
           | Even just naming a block (a function name) helped a lot.
           | Sure, you can document blocks of reactive code, which is what
           | we ended up doing but I felt like the self-document aspect
           | fell apart when I had to write a sentence above every block
           | as to why this intermediary transformation is necessary.
        
             | disantlor wrote:
             | For me, I think it comes from the ability to easily split a
             | stream at any point and create intermediate variables. I
             | get pretty obsessive about the variable naming (as I'm sure
             | many do here) but a good variable name is crucial to the
             | self-documenting concept. Also, creating more intermediate
             | values than strictly necessary, creates more opportunity to
             | flesh out the explanatory breadcrumb trail.
             | 
             | Because of the enforced formality of how data is flowing
             | around, the ability to split these streams up is trivial in
             | a way that was a revelation to me. In the past, I'd be far
             | less confident that I was going to mess up something
             | unintentionally, to the point where I would maybe not
             | bother.
             | 
             | And yeah, I think it's totally valid to take larger blocks
             | of streams/transformations and wrap in a named function
             | that takes a stream and returns a stream.
             | 
             | Over the years I've gotten out of the habit of always using
             | FRP for every problem. There are many cases where
             | async/await is totally fine and simple. I still always use
             | Ramda, which gives me the same self-documenting qualities
             | (which is really a function of the strictness of FP, not so
             | much the R in FRP, now that I think about it).
             | 
             | But whenever I have to coordinate multiple inputs with
             | different time delays (i.e. multiple AJAX requests or UI
             | input) or process a bunch of data where each item creates
             | its own stream of fetching and processing, the "reactive"
             | bit is extremely handy.
        
         | coding123 wrote:
         | I have the same experience. I remember when I was first
         | introduced to Rx(JS in my case) it was really fun to compose
         | async flows. I kept having to explain it to others and they
         | would sort of scratch their head. Eventually we stopped using
         | it. A year later I found some code still using it, and to my
         | own amazement, I was having trouble understanding it.
         | Lightbulb. It's like perl - it's write only.
        
         | christophilus wrote:
         | I feel the same way about RxJS. Moving from that to plain React
         | hooks and data flow saved me a ton of sanity on one project a
         | few years back.
        
         | marcosdumay wrote:
         | FRP is like OOP. For some problems, there is a level of
         | granularity where it's an absolute killer, and nothing gets
         | even nearly as effective. But if you write it with too much
         | granularity, it will completely destroy your code. (And with
         | too little granularity, it will be useless.)
         | 
         | This phrase alone: "data-flows that go through multiple
         | modules" is a very good indication that you broke things down
         | too much, and should have ditched the FRP abstraction on a
         | higher level.
        
         | slowmovintarget wrote:
         | Your problem seems to be with static typing, not FRP.
        
         | josteink wrote:
         | > As someone who had to maintain two applications written
         | entirely using the FRP Paradigm (Rx in Kotlin/Swift with a
         | heavy focus on FRP principles), I am fascinated the idea but I
         | absolutely hated the experience.
         | 
         | I had a similar experience maintaining and reviewing an
         | Angular+Typescript application at work. I was fascinated about
         | RX and was looking forward to see it in action.
         | 
         | In practice Angular exposes everything from its internal
         | framework and interfaces as Observables, making RX everywhere
         | the default.
         | 
         | The simplest things became mindbogglingly complex and asking
         | "what does this code actually _do_ " became the most frequent
         | code-review question.
         | 
         | When we were unable to get the application stable, I made a
         | renegade effort to eliminate all Observables and replace them
         | with standard, well-understood Promises instead.
         | 
         | The result was fewer lines of code, clearer code, fewer bugs
         | and more tests as bootstrapping/mocking a Promise-based API is
         | significantly less effort than doing the same for its
         | Observable-based counterpart.
         | 
         | It was a terrible experience all over and realistically (given
         | the choice) I'll never touch an Angular or RxJS based app ever
         | again. My team will just touch React for any new development
         | from now on.
        
           | hnthrway wrote:
           | >I made a renegade effort to eliminate all Observables and
           | replace them with standard, well-understood Promises instead.
           | 
           | Wow. You would have been better off ditching Angular
           | entirely, or sucking it up.
        
             | josteink wrote:
             | You're downvoted but entirely right.
             | 
             | Unfortunately I didn't have the time nor management buy-in
             | for doing that (a full rewrite), so instead I went for the
             | second best option, which was making the code we had at
             | least manageable.
        
         | ajuc wrote:
         | > Refactoring data-flows that go through multiple modules is a
         | huge hassle. Sometimes, we would spend hours just refactoring
         | data-passing, wrapping and unwrapping and tests surrounding
         | modules, because we needed to pass some additional values.
         | 
         | Same experience. Functional/declarative code is more elegant,
         | but a small change in desired behavior might require completely
         | different structure of the code (or an ugly hack). Meanwhile
         | imperative code changes much less even if it's less elegant.
        
         | zionic wrote:
         | I moved everything from RxSwift to Combine back with iOS (13?)
         | and was happy with the experience.
         | 
         | As for the "complexity", I largely solved this problem by
         | limiting dimensionality of stream handling to 1, and chaining
         | streams via explicit function calls so that I was never
         | map/flat mapping stream to stream to stream etc.
         | 
         | This made everything much easier to understand in my projects,
         | and also test etc.
         | 
         | But you're right as now that async/await is in Swift proper I'm
         | not sure it makes much sense anymore. There's still some
         | functionality I need that seems external (looks like async
         | sequence might help once I can use iOS16 as a min spec?).
         | Beyond the basic stuff, it's essential that I can:
         | 
         | 1) Define explicit timeouts that throw typed errors for every
         | step of the async process
         | 
         | 2) Have the ability to queue up an array of async operations
         | (each with their own timeouts), dispatch them in a serial
         | queue, then buffer their results to emit a single array, itself
         | with a global timeout
         | 
         | 3) While doing all of the above, I need a way to terminate
         | async actions "in flight" upon receipt of some signal, so that
         | a long running async queue can be aborted if necessary
         | 
         | Once all of the above is possible I'll probably go back and rip
         | out Rx (Combine) in a few years for a pure async-await
         | implementation, but that will take forever
        
           | manmal wrote:
           | AsyncSequence is good to go with iOS 13+ now, you can start
           | using it right away.
        
             | zionic wrote:
             | https://github.com/apple/swift-async-algorithms
             | 
             | Requires Xcode 14, which is still in beta and cannot push
             | to the App Store.
             | 
             | Also, Apple fucked their back port badly. It's supposedly
             | fixed now, but if you built an app that used async/await
             | anywhere in Xcode 13.X and a user installed running iOS
             | 12/13/up to 14.5 they'd crash on launch.
             | 
             | So I personally wouldn't trust it, and instead just push to
             | raise your iOS minimum. I've had no problems requiring
             | iOS15 in my projects over 1M installs
        
               | jshier wrote:
               | swift-async-algorithms can be used in earlier versions of
               | Xcode if you checkout an earlier tag. They just moved
               | forward more quickly.
               | 
               | Async / await's backport no longer causes crashes in
               | Xcode 13.4, but it does have the downside of being the
               | Swift 5.5 runtime, which has several unfixed issues,
               | unfortunately.
        
       | ghuntley wrote:
       | See also https://reflex-frp.org/
        
       | faleidel wrote:
       | Angular is using rxJs which is a reactive programming framework,
       | but I think it was an error to do so.
       | 
       | The angular project I am working on is now 5 years old and the
       | parts of the application that are the least understood are the
       | ones with more rxJs in it. We even have custom rxJs operators
       | that nobody understand anymore...
       | 
       | The way we do things now is to transform everything we can into
       | promises because it's more easy to work with.
       | 
       | With promises you have a few functions with which you can do
       | everything. With rxJs you have dozens of function with specific
       | use cases and most of them looks alike. It's too easy to not take
       | the right one and new peoples in the project needs to learn a lot
       | of things to understand the codebase.
       | 
       | I was interviewing some angular devs aand asked the question:
       | what is the difference between a promise and an observable and
       | 80% of the time the answer was "for observable you need to
       | sunscribe to get the result"). That shows a clear lack of
       | understand of rxJs.
       | 
       | Anybody had a better experience with angular and rxJs?
        
         | dhucerbin wrote:
         | Yes and no.
         | 
         | We found that rx.js is bad for coordination. I think
         | coordination is a big part of services in angular UI's. You
         | need to fetch some data, wait for it, ask for different thing,
         | maybe change some state. Promises and await are great for this
         | and especially await syntax is readable (go channels could be
         | even better). In rx.js you had to nest multiple switchMaps for
         | dependant queries and for state - you either produce state as a
         | stream result or you put some `tap` or `subscribe` with
         | `takeUntil`.
         | 
         | But rx.js shines with more complex user interactions - drag and
         | drops, brushes, interactive forms (angular has nice, reactive
         | form api). We even put some state machines inside streams, so
         | input signals produced events. and we had `scan` operator that
         | manipulated machine.
         | 
         | My personal issue with rx.js is that BehaviourSubject is leaky
         | - you can do anything to it, and break it's property of 'always
         | has a value'. It is nice if your service is a reactive value
         | that you can inject and transform or render using async pipe.
         | But you need to be careful what operators are you using on it.
        
         | pfooti wrote:
         | On the one hand, I absolutely love working with rxjs on a
         | fairly large angular app as a side project. It affords me the
         | chance to be clever with code, to reason about coordinating
         | multiple asychronous streams, and so on. Firestore gives me
         | observables of the queries I run where the data update
         | themselves, and the user generates events that turn into data
         | mutations. It is all just super great.
         | 
         | On the other hand, I recognize that doing this well and
         | correctly (understanding how to pipe together operators instead
         | of creating lots of intermediate subscriptions manually, which
         | I see a lot in example / stack overflow code) requires a high
         | level of understanding.
         | 
         | It is a whole change in how you think about event pipelines and
         | code structure. I don't think I would want to migrate my day
         | job systems to it, because then you need everyone on the team
         | to develop that understanding. I'm sure they _could_, but
         | working with promises and trad event handlers is a lot simpler,
         | as long as you keep the rest of the data / eventing pipelines
         | simple.
        
         | jinder wrote:
         | Yes - totally the opposite. In fact, I think the issue with
         | Angular is that they've not finished the work to make Angular
         | RX-everywhere (for example, reactive components need to be
         | manually plugged into Subjects at the moment).
         | 
         | With RxJS you should use it everywhere (observing state,
         | observing component inputs, side effects etc). It's when you
         | use it half-heartedly that you get problems with merging
         | different programming paradigms.
         | 
         | The biggest issue with RxJS that we've found is that some devs
         | have a super hard time getting to grips with the paradigm, and
         | if your project is mostly those types of people, it will end up
         | a disaster.
        
           | polyterative wrote:
           | > With RxJS you should use it everywhere (observing state,
           | observing component inputs, side effects etc). It's when you
           | use it half-heartedly that you get problems with merging
           | different programming paradigms
           | 
           | Yes, yes ,yes! I have been working with angular
           | professionally for five years and fell in love with rxjs. If
           | you manage to use it for everything, it really shines. Your
           | entire codebase becomes declarative and it works beautifully.
           | The only downside is that it takes some time to get it
           | started up from the ground up, but once you do making changes
           | and adding features becomes trivial. Try making smallish
           | pipes and comment their purpose. Break them modular pieces.
        
         | cphoover wrote:
         | I understand this paradigm within the context of stream
         | processing, but it seems like a weird way of modeling most REST
         | api-based web applications.
         | 
         | I feel like a promise-based model makes way more sense for most
         | simple web applications. Where you have a http request and
         | response, a promise model seems to suffice for most
         | applications communicating via http-requests to an API layer.
         | Modeling as a stream doesn't make sense to me, and seems like
         | it would over-complicate an otherwise simple mental-model.
         | 
         | In most of the simple web-applications I have encountered there
         | is one or more requests made to unique endpoints for data after
         | the document response has been completed. No need for handling
         | multiple events from the same endpoint, debouncing, multi-
         | casting, unsubscribing, back-pressure, or whatever else. These
         | operations seem to make way more sense in the context of stream
         | processing.
        
         | mrcartmeneses wrote:
         | Yeah totally the opposite. I really like RxJs and used it along
         | side my senior dev for good effect at my last perm for several
         | years. Our junior did find it a bit tricky sometimes though
         | (edit: I don't mean to imply you weren't "senior" enough, just
         | an observation that it was a new set of concepts to learn).
         | 
         | We would literally never use promises because we'd become so
         | comfortable with how we (and angular) managed the lifecycle of
         | observables. And we never ever used a async/await after some
         | nasty bugs in previous projects. We never started making our
         | own operators. And I think we never really got too complex with
         | it. RxJs marbles and learnrxjs were often consulted. But the
         | code seemed nice and clean and reliable. Testing was more
         | difficult and harder to understand but we got there.
         | 
         | We switched to using NgRx for our state quite early in the
         | project after a brief flirtation with observable services, so
         | that probably pushed us further down the observable route. We
         | kept NgRx up to date and found the helper functions really nice
         | so there wasn't too much boilerplate. Making new selectors and
         | integrating them into components with the async pipe is just so
         | damn easy with NgRx and RxJs. Effects would get mildly stupid
         | in terms of complexity and I did have a habit of hilariously
         | writing "these were your father's parentheses" at the end of
         | any particularly long set of closing parens... but yeah it
         | seemed to just work and give us relatively few bugs and none
         | that I recall were hard to track down. It was all very smooth.
         | 
         | The only thing I'd ever really complain about on that project
         | other than our build times was MSAL, which I hated with a
         | passion.
        
         | coding123 wrote:
         | Rx is a hot-shot, look what I can do, I am smarter than you,
         | paradigm and not much more. Source: I did that to co-workers
         | when I learned it.
        
       | revskill wrote:
       | FRP is simply the true way to build real time application.
        
         | marcosdumay wrote:
         | You mean interactive? I don't see how FRP helps with real time.
        
           | dllthomas wrote:
           | I expect the parent means having some portions of the output
           | change without user input, which isn't either of those if
           | we're being picky.
        
             | marcosdumay wrote:
             | Hum, I'll complain about calling it "being picky". We are
             | up to 3 completely different theories about what the GP
             | meant, and no way to tell them apart.
        
               | dllthomas wrote:
               | "Discerning"? :)
        
       | vladsanchez wrote:
       | As much as I'd love to learn Haskell, Lisp, OCaml or F#, try
       | https://reactivex.io/ and pick your language.
        
       | kgr wrote:
       | This short fun video demonstrates how FRP is related/similar to
       | spreadsheets:
       | 
       | https://www.youtube.com/watch?v=-fbq-_H6Lf4
        
       | InflexHQ wrote:
       | I'll be adding this to Inflex (https://inflex.io/), I have the
       | design worked out on paper. (But I'll be open sourcing it first
       | and releasing as a desktop app, and then get back to dev.)
       | 
       | It's also helpful to think of FRP in terms of "push" and "pull"
       | (for which there's a related paper by the same chap). This refers
       | to control flow. Behaviours are "pull" i.e. your program has to
       | pull from them. Events are "push" i.e. your program gets pushed
       | to, by some other active agent.
       | 
       | The trick is how one "makes things happen". If you want to pull
       | the latest tweets every 5 seconds, in reverse order, you might
       | have code that looks like:
       | 
       | timer(5).joinWith(latestTweets).map(reverse)
       | 
       | Similar to promises you're always building up more declarative
       | values. It's just that FRP has a clean semantic description.
       | There are laws, and no assumptions about time/imperative escape
       | hatches. It can be quite hard to use it practically for some
       | types of apps; space leaks and cycles are a challenge, and some
       | code can be messy. Research continues.
       | 
       | But for my simpler use-case, it's a very good fit. Spreadsheets
       | use "volatile" cells to side-step the whole issue of interacting
       | with time and the outside world, but it leaves a bad taste in the
       | mouth because it's a hack that makes state implicit. FRP brings a
       | strong mental framework to address this properly, rather than as
       | an afterthought.
        
         | shinzui wrote:
         | I got the impression that you're already using FRP for inflex.
        
       ___________________________________________________________________
       (page generated 2022-08-16 23:01 UTC)