ekmett/lens

Add `toAlternativeOf`?

Closed this issue · 7 comments

I use this function without issues:

-- | A more general `toListOf` that collects targets into any `Alternative`.
toAlternativeOf :: (Alternative f) => Getting (Alt f a) s a -> s -> f a
toAlternativeOf l = let alt = Alt . pure in getAlt . view (l . to alt)

https://github.com/sjshuck/hs-pcre2/blob/2d01498056569905abc643fdffa697efbbd6c08c/src/hs/Text/Regex/Pcre2/Internal.hs#L130-L132

I use it as a simple way to unify "find-all" (f ~ []) and "find-one" (f ~ Maybe) in a single implementation. It will attempt to fill up the Alternative or run out of targets, whichever comes first. But I don't have much insight into performance implications. Maybe there's some kind of Endo-based implementation that's possible and preferable (à la toListOf?

Any other considerations?

ekmett commented

The main consideration is that

toAlternativeOf :: Alternative f => Getting (Alt f a) s a -> s -> f a

should be weakened to

toAlternativeOf :: Applicative f => Getting (Alt f a) s a -> s -> f a

then it will only require an Applicative when applied to a Getter, but will require Alternative when used with a Fold (because the Getting itself will require it for Alts Applicative).

Thanks for the feedback.

I'll prepare a PR. Meanwhile, I'm conflicted about the name toAlternativeOf, now moreso because Alternative doesn't exist anywhere in the type.

Possibilities:

  • toAltOf (because Alt is in the type)
  • toAOf ("A" as in sequenceA or asum)
  • toPureOf/pureOf (because really what it does is call pure on targets, and if through a Fold, <|>s them together)

Honestly I like toPureOf/pureOf.

ekmett commented

I admit I'm not a big fan of lots of camelCase. I'd probably go altOf.

ekmett commented

derp. this is asumOf

I think it's asumOf (l . to pure) that also support Applicative for single-target optics.

ekmett commented

Yeah. I guess altOf is probably the right thing then. I'm not a big fan of coining new names if I can avoid it, but I'm much less a fan of toXyzOf proliferating.

"Also supporting a weaker constraint for single target optics" is generally a thing, sumOf and productOf already do that.

Right, whereas view, which is named after the weaker action ("just look at a thing"), has this sometimes surprising behavior of mushing targets together if you accidentally request the stronger action by having multiple targets—altOf gives you a heads-up that something mushy is liable to happen. 🙂