Integrate witherable and lens. Based on the ideas from https://chrispenner.ca/posts/witherable-optics but with a more combinator-based approach to restore full compatibility with lens combinators like `set` and `over`. Additionally, this approach gets rid of `Maybe` wrappers in results that are always `Just`. This library is based on a variant of `Traversal`s with the type `forall f. Applicative f => ((a-> Withering f b) -> s -> f t)`. Note that this type is absolutely not an optic due to the `Withering` wrapper, but it's really close. It composes on either side with lenses and traversals with `(.)` and that composition maintains the filtering type. No type alias is provided for this type because type aliases containing a `forall` cause problems with subsumption. The core tool for creating values with these types is ```haskell withered :: (Applicative f, Witherable t) => (a -> Withering f b) -> t a -> f (t b) ``` One tool for working with the types is ```haskell mapMaybeOf :: ((a -> Withering Identity b) -> s -> Identity t) -> (a -> Maybe b) -> s -> t ``` These can be used like such ```haskell ghci> let z = M.fromList [('a', ["1", "2", "3"]), ('b', ["4", "Alpaca", "6"])] ghci> z & mapMaybeOf (traverse . withered) (readMaybe :: String -> Maybe Int) fromList [('a',[1,2,3]),('b',[4,6])] ghci> z & mapMaybeOf (withered . traverse) (readMaybe :: String -> Maybe Int) fromList [('a',[1,2,3])] ``` As those results demonstrate, the location of the `withered` combinator controls where the pruning stops. It functions as a kind of catch combinator in this sense. Of course, `filterOf` is provided as well ```haskell filterOf :: ((a -> Withering Identity a) -> s -> Identity s) -> (a -> Bool) -> s -> s ``` ```haskell ghci> [[1, 2, 3], [4, 5, 6]] & filterOf (traverse . withered) even [[2],[4,6]] ``` Traversals that might fail can be combined with the `decayed` combinator to cause them to completely remove a value that they otherwise would ignore ```haskell ghci> [('a', Right 1), ('b', Left 2), ('c', Left 3)] & filterOf (withered . _2 . _Left) even [('a',Right 1),('b',Left 2)] ghci> [('a', Right 1), ('b', Left 2), ('c', Left 3)] & filterOf (withered . _2 . (_Left `failing` decayed)) even [('b',Left 2)] ``` In the first case, the `'a'` value is returned because the filter doesn't find any non-even values under the `Right` value when it's looking under the `_Left` prism. In the second case, the failure of the `_Left` prism results in falling back on `decayed` to remove the branch. Compatibility with normal lens operations can be restored with `unwithered`. This can be especially useful when combined with `guarded`, which acts somewhat like lens's `filtered` but it prunes the structure up to the next `withered`. ```haskell unwithered :: Functor f => (a -> f b) -> a -> Withering f b guarded :: Applicative f => (a -> Bool) -> (a -> Withering f b) -> a -> Withering f b ``` ```haskell ghci> [[1,2],[],[1,3,9],[],[],[6,4,7],[]] & withered . guarded (not . null) . unwithered . traverse +~ 10 [[11,12],[11,13,19],[16,14,17]] ``` Note that pruning out the empty lists happens in-line with the modification of the other elements. An additional combinator is provided combining `withered` and `unwithered` for when you want to change the pruning depth ```haskell rewithered :: (Applicative f, Witherable t) => (a -> Withering f b) -> t a -> Withering f (t b) ``` ```haskell ghci> [[1,2],[],[1,3,9],[],[],[6,4,7],[]] & (withered . guarded (not . null) . rewithered . guarded even . unwithered) +~ 10 [[12],[],[16,14]] ``` In that example, the first `guarded` strips out null lists in the input. The `rewithered` descends into the sublists and sets each of them as the catch point for later pruning. The second `guarded` strips out all non-even entries in each list. The `unwithered` restores compatibility with lens combinators like `(+~)`, which is used to modify every remaining focused value. Note the presence of the `[]` in the output list. The `guarded` combinator violates the lens laws in the same manner as `filtered`, where behavior might change with refactoring. This doesn't mean it's dangerous to use, merely that you have to pay attention to changes in behavior when refactoring chains involving it.