First of all, thank you for writing this library, it is really excellent.
I was experimenting with zoomOne and zoomAll, and was trying to come up with a slightly different, more uniform approach. The idea is that if we can express the UI type as s -> f s for some Applicativef`, then you get lifting over all optics "for free". I came up with this:
newtype Markup a = Markup (Array (HTML a))
instance functorMarkup :: Functor Markup where ...
instance alternativeMarkup :: Alternative Markup where ...
newtype UI state = UI (state -> NonEmpty Markup state)
Then the core combinators become trivial:
lens :: forall a b. LensP a b -> UI b -> UI a
lens l (UI ui) = UI (l ui)
traverse :: forall a b. TraversalP a b -> UI b -> UI a
traverse t (UI ui) = UI (t ui)
The key is the NonEmpty applicative functor which captures something like Halogen's mergeWith combinator, combining components in parallel, keeping the latest state from each:
data NonEmpty f state = NonEmpty state (f state)
instance functorNonEmpty :: (Functor f) => Functor (NonEmpty f) where
map f (NonEmpty state fa) = NonEmpty (f state) (map f fa)
instance applyNonEmpty :: (Alt f) => Apply (NonEmpty f) where
apply (NonEmpty f fs) (NonEmpty x xs) = NonEmpty (f x) (map ($ x) fs <|> map f xs)
instance applicativeNonEmpty :: (Alternative f) => Applicative (NonEmpty f) where
pure a = NonEmpty a empty
I think this could generalize nicely in a few ways:
- We can use other
Applicatives instead of just Markup, including Aff, Producer, etc.
- We can use
Eff inside UI to support third-party widgets.
Right now, I think this library has the best story for component composition I've seen in a PureScript library, but it would be really great to be able to handle third-party components and things like AJAX too.
I know this is a fairly big change, but would you take a PR?
Thanks
First of all, thank you for writing this library, it is really excellent.
I was experimenting with
zoomOneandzoomAll, and was trying to come up with a slightly different, more uniform approach. The idea is that if we can express theUItype ass -> f sfor someApplicativef`, then you get lifting over all optics "for free". I came up with this:Then the core combinators become trivial:
The key is the
NonEmptyapplicative functor which captures something like Halogen'smergeWithcombinator, combining components in parallel, keeping the latest state from each:I think this could generalize nicely in a few ways:
Applicatives instead of justMarkup, includingAff,Producer, etc.EffinsideUIto support third-party widgets.Right now, I think this library has the best story for component composition I've seen in a PureScript library, but it would be really great to be able to handle third-party components and things like AJAX too.
I know this is a fairly big change, but would you take a PR?
Thanks