raquo/Airstream

Cats effect support

hejfelix opened this issue · 5 comments

I would love to see some way of using an effect type with this library. I understand that the library itself doesn't need it, but interfacing with pure fp code, it would make sense to allow observers to pass wrapped effects instead of effectful functions.

raquo commented

Hi, do you mean basically having a conversion from A => IO[Unit] to Observer[A]?

This particular one should be easy, but I don't think I want to maintain a cats-airstream integration. Too much admin overhead between version updates and stuff. I would prefer to just publish a few functions on laminar.dev/examples that users could easily contribute to and copy-paste into their projects.

And since I do not use Cats with Airstream myself, I'll need someone who wants to use these two together to tell me what kind of integration would they would want (I imagine there's more than just this one conversion).

I would rather have a conversion from A => F[Unit] with some appropriate constraint on F. I understand that this may be a tall order. I'm trying to use Laminar, and I am still a bit confused as to why it's not just using e.g. fs2?

raquo commented

The reasons for using Airstream is at the top of the readme – https://github.com/raquo/Airstream/ points 1 and 2 being the most obvious that FS2 lacks. Aside from that, FS2 is rather complex and designed for concurrent streaming on the backend. It's not the simplest solution for declarative UI in a single threaded environment.

If you really want to use FS2, you can create conversions from Airstream observables to FS2 and back. You will lose some safety doing this, but it would work. You'd need to understand both libraries to do this though. I don't have much experience with FS2 so I can't really help other than explain things about Airstream that aren't explained in the docs.

Regarding A => F[Unit]... if you can convert this to A => Unit, just wrap it into Observer() and you have an observer. I'm not a cats expert so I don't know what kind of constraints you'd want on F. Whichever ones would make it possible to run your effect. So I guess F: Effect? I really don't remember such things. You might also want to handle errors properly, the Observer companion object provides the methods for that too (or just extend Observer).

Thanks for elaborating. I get it now - one source of confusion in laminar comes from the fact that the api doesn't make it clear which functions are effectful, e.g. "Is it safe to add an observer here?". This was one of my reasons for this ticket. Furthermore, I'm using fs2 on the backend with shared code for the front end - this currently means juggling two different streaming libraries which can feel overwhelming.
Hopefully I can open source the thing I'm working on to make it more clear what I'm trying to do.
I think it's safe to close this issue.

raquo commented

I can definitely see how Laminar could interfere with traditional FP style. It's purposefuly not designed for tracking effects because I don't really see that pattern as beneficial for UI development. Laminar's focus is on leveraging a simple, forgiving observables implementation that is strict about things that I think are important for safety (e.g. proper differentiation of Streams and Signals) but lax about things I don't think are carrying their weight in UI development.

To be honest I don't really know what you mean by "Is it safe to add an observer here?". I'm not sure what kind of safety you're referring to. Memory management questions are easily answered by ownership. You always know when the subscription will start and end (typically on mount and unmount of the element which you're using), whether it will run immediately on mount (signal) or wait until events start coming in (EventStream), etc.

I admit that it is a bit annoying that Airstream doesn't compile on the JVM, but that's because it's not designed to run there. If it was, it would look a lot more like FS2, with all the complexity downsides of that. For me the current situation is a good tradeoff. For shared logic, an Airstream-FS2 bridge like I mentioned might do the trick.

Outwatch is designed for traditional FP, and I think it's streaming library agnostic nowadays, so you may want to try that with FS2. Personally I'm not convinced that combining virtual DOM with FRP is a good idea (details here) but some people are certainly happy with it.