sharkdp / purescript-flare

A special-purpose UI library for Purescript
286 stars 17 forks source link

Run an inner Flare with access to current value #27

Closed koterpillar closed 7 years ago

koterpillar commented 7 years ago

Example 14 in the docs shows how to do a component dependent on the previous values in the UI, but it requires separate markup and is hard to replace an existing UI with - the types have to be changed all around.

This PR adds a function to set up an inner UI with access to the current value - see updated example 14 for motivation and usage.

There are a few rough edges that I hope to get some advice on:

The signature gets UI close to being a Monad, but I decided not to implement the instance because the performance and user experience of recreating the inner UI each time would be awful if it's used as a base for apply.

sharkdp commented 7 years ago

Thank you, that sounds super exciting!

Unfortunately, I won't have time to properly review this during the next days. I'll get back to you soon.

sharkdp commented 7 years ago

First of all, this is really great stuff! I'm very excited and still slightly surprised, that this is possible :smile:

bodil/purescript-signal#60 would simplify the types - right now there's an ugly Maybe to work around.

Can we get rid of the Maybe in the type signature if Signal.get would exist? If this is the case, I'd be okay with adding a (FFI) helper to Flare for now (which could be removed if the PR is merged).

An empty container for the inner UI is appended to the body (but immediately reattached where needed) - to change this either ElementId or element cleanup logic needs changing.

I'm completely okay with this. We can still revisit this if it turns out to be problematic.

koterpillar commented 7 years ago

Removed Maybe from the signature using a copied-over Signal.get.

sharkdp commented 7 years ago

Thank you very much!

The signature gets UI close to being a Monad, but I decided not to implement the instance because the performance and user experience of recreating the inner UI each time would be awful if it's used as a base for apply.

I agree, but I also really like that this allows us to write example 14 as

ui14 :: forall e m. UI e (H.Markup m)
ui14 = do
  domain ← select "Color domain" (HSL :| [RGB]) showDomain
  color ← uiColor domain
  pure (toHTML color)

It's quite interesting that UI e can be made into a monad, even though Signal cannot. If I understand this correctly, this is due to Signal.get which is basically a natural transformation from Signal to Eff e.

koterpillar commented 7 years ago

I can't see why a similar technique won't work for a Signal. I'm not sure about performance degradation/memory leaks, but the implementation should be clear, with a Channel to pass values across.