Skip to content

Port selected functions from Control.Lens.Plated#379

Merged
arybczak merged 6 commits intomasterfrom
plated
Dec 21, 2021
Merged

Port selected functions from Control.Lens.Plated#379
arybczak merged 6 commits intomasterfrom
plated

Conversation

@arybczak
Copy link
Copy Markdown
Collaborator

It needs a bit of polish wrt. documentation. Do we want to have it in 0.4?

Copy link
Copy Markdown

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would definitely like to have these!


-- | Rewrite recursively over part of a larger structure.
rewriteOn :: (Is k A_Setter, Plated a) => Optic k is s t a a -> (a -> Maybe a) -> s -> t
rewriteOn b = over b . rewrite
Copy link
Copy Markdown

@michaelpj michaelpj Jun 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have wondered in the past why these functions exist (in lens). Composing rewrite with over b seems like something we could expect our users to do. After all, a user of a lens library is probably pretty used to stringing together combinations of transformations.

Maybe we can do without the *On variants.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied the API of lens verbatim since I never used Plated, but you're right, it makes sense to provide MVP and extend if necessary.

-------------------------------------------------------------------------------

-- | Perform a fold-like computation on each value, technically a paramorphism.
paraOf :: Is k A_Fold => Optic' k is a a -> (a -> [r] -> r) -> a -> r
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know to what degree we want to mimic the exact structure of lens, but arguably it would make sense to put the *Of variants in the modules for the optics they use, e.g. paraOf in Fold, traverseOf in Setter etc, leaving this module to contain the versions that actually use Plated.

(Which I just noticed is exactly how it is for partsOf already.)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I moved paraOf to Optics.Fold and removed para and parts for now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't read this suggestion well enough it seems. Yeah, having Optics.Plated only have the functions with plate applied also sounds reasonable.

universeOf :: Is k A_Fold => Optic' k is a a -> a -> [a]
universeOf l = go
where
go a = a : foldMapOf l go a
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know lens doesn't do this either, but is there a reason not to define universe* fucntions in terms of cosmos* and toListOf?

Copy link
Copy Markdown
Collaborator Author

@arybczak arybczak Dec 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea, sadly I never used these functions so have no intuition.

@fishtreesugar fishtreesugar mentioned this pull request Oct 31, 2021
@Boarders
Copy link
Copy Markdown

Any updates on this PR? I'd be happy to help get it over the line.

@mikeplus64
Copy link
Copy Markdown

I wonder if Plated would be better off in its own package or in recursion-schemes where it IMO fits in very well. It's a really useful typeclass and it would be nice if lens and optics had compatibility with it as well.

class Plated a where
  plate :: Applicative f => (a -> f b) -> s -> f t

I don't know if that's impossible with optics' Traversal.

@arybczak
Copy link
Copy Markdown
Collaborator Author

arybczak commented Dec 7, 2021

I've updated the PR and stripped the API down. Could you tell me if that's ok? I've never used Plated so can't really tell if the API is now much harder to use.

I'm even wondering about removing Plate and all functions without the Of suffix that just apply the Of variant to plate. But maybe that's too much?

@arybczak
Copy link
Copy Markdown
Collaborator Author

arybczak commented Dec 7, 2021

I'm even wondering about removing Plate and all functions without the Of suffix

The last commit performs that experiment. It looks the most reasonable to me 🤔 Thoughts?

@arybczak
Copy link
Copy Markdown
Collaborator Author

arybczak commented Dec 7, 2021

@mikeplus64 this is a good idea. optics can reuse Plated in the form you've written by simply wrapping it in traversalVL.

The only problem is the default instance would be missing, which might or might not be a big deal.

@phadej
Copy link
Copy Markdown
Contributor

phadej commented Dec 7, 2021

In my opinion Plated type-class shouldn't be in lens and shouldn't be copied to optics either. It's just a traversal for immediate children. (It would be silly to have Traversable in lens, and we pulled TraversableWithIndex out of it too).

EDIT: I'm 👍 with adding non Plated specific combinators. I'm 👎 for adding the class.

@arybczak arybczak changed the title [WIP] Add Optics.Plated Port selected function from Control.Lens.Plated Dec 7, 2021
@arybczak arybczak changed the title Port selected function from Control.Lens.Plated Port selected functions from Control.Lens.Plated Dec 7, 2021
@arybczak
Copy link
Copy Markdown
Collaborator Author

arybczak commented Dec 7, 2021

@phadej I'm with you on this one. I don't see the point of having Plated and *Of variants that are independent of it.

I think this PR can be merged as-is.

@arybczak arybczak requested a review from phadej December 7, 2021 19:57
Copy link
Copy Markdown

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me, very neat!


-- | Transform every element by recursively applying a given 'Setter' in a
-- bottom-up manner.
transformOf :: Is k A_Setter => Optic k is a b a b -> (b -> b) -> a -> b
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it deliberate that the *OnOf variants are left out? They are useful when you e.g. want to transform all Pats inside Exp:

transformOnOf patExps expPlated modifyPat :: Exp -> Exp where
  patExps :: Setter' Pat Exp
  expPlated :: Setter' Pat Pat
  modifyPlated :: Pat -> Pat

Of course I can do over patExps (transformOf expPlated modifyPlated)...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course I can do over patExps (transformOf expPlated modifyPlated)...

Yeah, that's what was also mentioned in #379 (comment), I think these are a bit excessive.

We can always add them later if there is enough demand.

universeOf :: Is k A_Fold => Optic' k is a a -> a -> [a]
universeOf l = go
where
go a = a : foldMapOf l go a
Copy link
Copy Markdown
Contributor

@phadej phadej Dec 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is slow for trees. ++ can easily make this quadratic. I don't know why DList = Endo [a] is not used here (and in lens) instead.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give an example?

I don't know why DList = Endo [a] is not used here (and in lens) instead.

Me neither, I assume since lens has it like that it's fine 🤔 It can be optimized later if necessary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated PR to reflect changes made to lens.

@arybczak arybczak merged commit 18ad71d into master Dec 21, 2021
@arybczak arybczak deleted the plated branch December 21, 2021 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants