|
2 | 2 |
|
3 | 3 | module Data.Lens.Fold |
4 | 4 | ( (^?), (^..) |
5 | | - , preview, foldOf, foldMapOf, foldrOf, foldlOf, toListOf, has, hasn't |
6 | | - , replicated, filtered |
| 5 | + , preview, foldOf, foldMapOf, foldrOf, foldlOf, toListOf, firstOf, lastOf |
| 6 | + , maximumOf, minimumOf, allOf, anyOf, andOf, orOf, elemOf, notElemOf, sumOf |
| 7 | + , productOf, lengthOf, findOf, sequenceOf_, has, hasn't, replicated, filtered |
7 | 8 | ) where |
8 | 9 |
|
9 | 10 | import Prelude |
10 | 11 | import Data.Const |
11 | 12 | import Data.Maybe |
12 | 13 | import Data.List |
13 | 14 | import Data.Either |
| 15 | +import Data.Tuple |
14 | 16 | import Data.Monoid |
15 | 17 | import Data.Maybe.First |
| 18 | +import Data.Maybe.Last |
16 | 19 | import Data.Monoid.Endo |
17 | 20 | import Data.Monoid.Conj |
18 | 21 | import Data.Monoid.Disj |
19 | 22 | import Data.Monoid.Dual |
| 23 | +import Data.Monoid.Additive |
| 24 | +import Data.Monoid.Multiplicative |
20 | 25 | import Data.Functor.Contravariant |
21 | 26 | import Data.Foldable |
22 | 27 | import Data.Profunctor |
@@ -54,6 +59,69 @@ foldrOf p f r = flip runEndo r <<< foldMapOf p (Endo <<< f) |
54 | 59 | foldlOf :: forall s t a b r. Fold (Dual (Endo r)) s t a b -> (r -> a -> r) -> r -> s -> r |
55 | 60 | foldlOf p f r = flip runEndo r <<< runDual <<< foldMapOf p (Dual <<< Endo <<< flip f) |
56 | 61 |
|
| 62 | +-- | Whether all foci of a `Fold` satisfy a predicate. |
| 63 | +allOf :: forall s t a b r. (BooleanAlgebra r) => Fold (Conj r) s t a b -> (a -> r) -> s -> r |
| 64 | +allOf p f = runConj <<< foldMapOf p (Conj <<< f) |
| 65 | + |
| 66 | +-- | Whether any focus of a `Fold` satisfies a predicate. |
| 67 | +anyOf :: forall s t a b r. (BooleanAlgebra r) => Fold (Disj r) s t a b -> (a -> r) -> s -> r |
| 68 | +anyOf p f = runDisj <<< foldMapOf p (Disj <<< f) |
| 69 | + |
| 70 | +-- | The conjunction of all foci of a `Fold`. |
| 71 | +andOf :: forall s t a b. (BooleanAlgebra a) => Fold (Conj a) s t a b -> s -> a |
| 72 | +andOf p = allOf p id |
| 73 | + |
| 74 | +-- | The disjunction of all foci of a `Fold`. |
| 75 | +orOf :: forall s t a b. (BooleanAlgebra a) => Fold (Disj a) s t a b -> s -> a |
| 76 | +orOf p = anyOf p id |
| 77 | + |
| 78 | +-- | Whether a `Fold` contains a given element. |
| 79 | +elemOf :: forall s t a b. (Eq a) => Fold (Disj Boolean) s t a b -> a -> s -> Boolean |
| 80 | +elemOf p a = anyOf p (== a) |
| 81 | + |
| 82 | +-- | Whether a `Fold` not contains a given element. |
| 83 | +notElemOf :: forall s t a b. (Eq a) => Fold (Conj Boolean) s t a b -> a -> s -> Boolean |
| 84 | +notElemOf p a = allOf p (/= a) |
| 85 | + |
| 86 | +-- | The sum of all foci of a `Fold`. |
| 87 | +sumOf :: forall s t a b. (Semiring a) => Fold (Additive a) s t a b -> s -> a |
| 88 | +sumOf p = runAdditive <<< foldMapOf p Additive |
| 89 | + |
| 90 | +-- | The product of all foci of a `Fold`. |
| 91 | +productOf :: forall s t a b. (Semiring a) => Fold (Multiplicative a) s t a b -> s -> a |
| 92 | +productOf p = runMultiplicative <<< foldMapOf p Multiplicative |
| 93 | + |
| 94 | +-- | The number of foci of a `Fold`. |
| 95 | +lengthOf :: forall s t a b. Fold (Additive Int) s t a b -> s -> Int |
| 96 | +lengthOf p = runAdditive <<< foldMapOf p (const $ Additive 1) |
| 97 | + |
| 98 | +-- | The first focus of a `Fold`, if there is any. Synonym for `preview`. |
| 99 | +firstOf :: forall s t a b. Fold (First a) s t a b -> s -> Maybe a |
| 100 | +firstOf p = runFirst <<< foldMapOf p (First <<< Just) |
| 101 | + |
| 102 | +-- | The last focus of a `Fold`, if there is any. |
| 103 | +lastOf :: forall s t a b. Fold (Last a) s t a b -> s -> Maybe a |
| 104 | +lastOf p = runLast <<< foldMapOf p (Last <<< Just) |
| 105 | + |
| 106 | +-- | The maximum of all foci of a `Fold`, if there is any. |
| 107 | +maximumOf :: forall s t a b. (Ord a) => Fold (Endo (Maybe a)) s t a b -> s -> Maybe a |
| 108 | +maximumOf p = foldrOf p (\a -> Just <<< maybe a (max a)) Nothing where |
| 109 | + max a b = if a > b then a else b |
| 110 | + |
| 111 | +-- | The minimum of all foci of a `Fold`, if there is any. |
| 112 | +minimumOf :: forall s t a b. (Ord a) => Fold (Endo (Maybe a)) s t a b -> s -> Maybe a |
| 113 | +minimumOf p = foldrOf p (\a -> Just <<< maybe a (min a)) Nothing where |
| 114 | + min a b = if a > b then a else b |
| 115 | + |
| 116 | +-- | Find the first focus of a `Fold` that satisfies a predicate, if there is any. |
| 117 | +findOf :: forall s t a b. Fold (Endo (Maybe a)) s t a b -> (a -> Boolean) -> s -> Maybe a |
| 118 | +findOf p f = foldrOf p (\a -> maybe (if f a then Just a else Nothing) Just) Nothing |
| 119 | + |
| 120 | +-- | Sequence the foci of a `Fold`, pulling out an `Applicative`, and ignore |
| 121 | +-- | the result. If you need the result, see `sequenceOf` for `Traversal`s. |
| 122 | +sequenceOf_ :: forall f s t a b. (Applicative f) => Fold (Endo (f Unit)) s t (f a) b -> s -> f Unit |
| 123 | +sequenceOf_ p = flip runEndo (pure unit) <<< foldMapOf p \f -> Endo (f *>) |
| 124 | + |
57 | 125 | -- | Collects the foci of a `Fold` into a list. |
58 | 126 | toListOf :: forall s t a b. Fold (Endo (List a)) s t a b -> s -> List a |
59 | 127 | toListOf p = foldrOf p (:) Nil |
@@ -87,3 +155,10 @@ folded |
87 | 155 | :: forall f g a b t r. (Applicative f, Contravariant f, Foldable g) |
88 | 156 | => Optic (Star f) (g a) b a t |
89 | 157 | folded p = Star $ foldr (\a r -> runStar p a *> r) (coerce $ pure unit) |
| 158 | + |
| 159 | +-- | Builds a `Fold` using an unfold. |
| 160 | +unfolded |
| 161 | + :: forall f s t a b. (Applicative f, Contravariant f) |
| 162 | + => (s -> Maybe (Tuple a s)) -> Optic (Star f) s t a b |
| 163 | +unfolded f p = Star go where |
| 164 | + go = maybe (coerce $ pure unit) (\(Tuple a s) -> runStar p a *> go s) <<< f |
0 commit comments