Skip to content

Question: different approach to TraversalP, LensP etc. #4

@paf31

Description

@paf31

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions