lens 3.2 → 3.3
raw patch · 37 files changed
+1139/−463 lines, 37 filesdep +splitdep +vectordep +voiddep ~basedep ~comonaddep ~comonads-fd
Dependencies added: split, vector, void
Dependency ranges changed: base, comonad, comonads-fd, transformers
Files
- .gitignore +2/−0
- CHANGELOG.markdown +18/−0
- benchmarks/unsafe.hs +63/−0
- lens.cabal +29/−4
- src/Control/Lens.hs +1/−1
- src/Control/Lens/Action.hs +5/−3
- src/Control/Lens/Fold.hs +4/−2
- src/Control/Lens/Getter.hs +1/−0
- src/Control/Lens/IndexedFold.hs +141/−11
- src/Control/Lens/IndexedLens.hs +10/−0
- src/Control/Lens/IndexedSetter.hs +6/−5
- src/Control/Lens/IndexedTraversal.hs +13/−0
- src/Control/Lens/Internal.hs +9/−170
- src/Control/Lens/Iso.hs +10/−7
- src/Control/Lens/Plated.hs +14/−11
- src/Control/Lens/Representable.hs +6/−3
- src/Control/Lens/Setter.hs +20/−3
- src/Control/Lens/Simple.hs +6/−1
- src/Control/Lens/TH.hs +1/−0
- src/Control/Lens/Traversal.hs +11/−11
- src/Control/Lens/Type.hs +0/−18
- src/Control/Lens/Unsafe.hs +218/−0
- src/Control/Lens/WithIndex.hs +24/−9
- src/Control/Lens/Zipper.hs +2/−2
- src/Control/Lens/Zoom.hs +14/−12
- src/Data/ByteString/Lazy/Lens.hs +4/−5
- src/Data/ByteString/Strict/Lens.hs +3/−4
- src/Data/Data/Lens.hs +2/−1
- src/Data/HashSet/Lens.hs +1/−2
- src/Data/IntSet/Lens.hs +1/−2
- src/Data/List/Lens.hs +11/−158
- src/Data/List/Split/Lens.hs +195/−0
- src/Data/Set/Lens.hs +1/−2
- src/Data/Tree/Lens.hs +1/−2
- src/Data/Vector/Generic/Lens.hs +150/−0
- src/Data/Vector/Lens.hs +127/−0
- tests/hunit.hs +15/−14
.gitignore view
@@ -5,3 +5,5 @@ tags wip .DS_Store+.*.swp+.*.swo
CHANGELOG.markdown view
@@ -1,3 +1,21 @@+3.3+---+* Redefined `simple` and moved it to `Control.Lens.Iso`. Instead of using `simple l` you can now compose `l.simple` or `simple.l` providing more nuanced control and a more compositional API.+* Moved the various `foo#` combinators used to emit cleaner core into an unexported module, `Control.Lens.Unsafe`. This removes `MagicHash` from the public API.+* Removed the `bazaar#` and `runBazaar#` coercions that caused issues on GHC HEAD.+* Changed the default definition of `plate` to `uniplate` from `ignored`.+* Added `Data.Vector.Lens` and instances for `Data.Vector`.+* Added support for the `split` package, which is now part of the Haskell platform.+* Removed redundant `Data.List.traverseList`. Use `itraversed` or `traverse` instead.+* Moved `(:<->)` to `Control.Lens.Simple`.+* Fixed a bug in `Control.Lens.TH` that was causing `makeIso` not to work.+* Added `lifted` to `Control.Lens.Setter` for mapping over monads.+* Added `beside` to `Control.Lens.Traversal`.+* Removed the operators from `Data.List.Lens`, they broke the overall pattern of the rest of the API, and were terrible clutter.+* Fixed a bug that caused `resultAt` to give wrong answers most of the time.+* Changed `resultAt` to an `IndexedLens` and moved it to `Control.Lens.IndexedLens`+* Changed `ignored` to an `IndexedTraversal` and moved it to `Control.Lens.IndexedTraversal`+ 3.2 --- * Made `elementOf` lazier and moved it from `Control.Lens.Traversal` to `Control.Lens.Plated`.
+ benchmarks/unsafe.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE BangPatterns #-}+module Main where++import Control.Lens+import Control.Lens.Internal+import Control.Exception++import Criterion.Main+import Criterion.Config++import GHC.Exts++overS :: Setting s t a b -> (a -> b) -> s -> t+overS l f = runMutator . l (Mutator . f)+{-# INLINE overS #-}++mappedS :: Setting [a] [b] a b+mappedS f = Mutator . map (runMutator . f)+{-# INLINE mappedS #-}++overU :: Setting s t a b -> (a -> b) -> s -> t+overU = over+{-# INLINE overU #-}++mappedU :: Setting [a] [b] a b+mappedU = mapped+{-# INLINE mappedU #-}+++-- Need to eta-expand for full inlining in the NOINLINE cases?+-- Doesn't seem to make a difference, though.++mapSN :: (a -> b) -> [a] -> [b]+mapSN f l = overS mappedS f l+{-# NOINLINE mapSN #-}++mapSI :: (a -> b) -> [a] -> [b]+mapSI f = overS mappedS f+{-# INLINE mapSI #-}++mapUN :: (a -> b) -> [a] -> [b]+mapUN f l = overU mappedU f l+{-# NOINLINE mapUN #-}++mapUI :: (a -> b) -> [a] -> [b]+mapUI f = overU mappedU f+{-# INLINE mapUI #-}++main :: IO ()+main = do+ let n = 1000+ l = replicate n "hi"; f = length+ --l = replicate n (); f = (\ _ -> ())+ --l = replicate n (); f = (\ !_ -> ()) -- strange results+ --l = replicate n (); f = lazy (\_ -> ())+ defaultMainWith config (return ())+ [ bench "map safe noinline" $ nf (mapSN f) l+ , bench "map safe inline" $ nf (mapSI f) l+ , bench "map unsafe noinline" $ nf (mapUN f) l+ , bench "map unsafe inline" $ nf (mapUI f) l+ ]+ where+ config = defaultConfig { cfgSamples = ljust 1000 }
lens.cabal view
@@ -1,6 +1,6 @@ name: lens category: Data, Lenses-version: 3.2+version: 3.3 license: BSD3 cabal-version: >= 1.8 license-file: LICENSE@@ -37,7 +37,7 @@ . The core of this hierarchy looks like: .- <<https://github.com/ekmett/lens/wiki/images/Hierarchy-3.2.png>>+ <<http://i.imgur.com/keOs9.png>> . You can compose any two elements of the hierarchy above using (.) from the Prelude, and you can use any element of the hierarchy as any type it links to above it.@@ -82,7 +82,7 @@ exotic functionality, (/e.g./ getters, setters, indexed folds, isomorphisms). build-type: Simple-tested-with: GHC == 7.4.1, GHC == 7.6.0, GHC == 7.7.20120822, GHC == 7.7.20120830+tested-with: GHC == 7.4.1, GHC == 7.6.1 extra-source-files: .travis.yml .ghci@@ -151,9 +151,12 @@ hashable == 1.1.*, mtl >= 2.1.1 && < 2.2, semigroups >= 0.8.4 && < 0.9,+ split == 0.2.*, text >= 0.11 && < 0.12, transformers >= 0.3 && < 0.4,- unordered-containers >= 0.2 && < 0.3+ unordered-containers >= 0.2 && < 0.3,+ vector >= 0.9 && < 0.11,+ void >= 0.5 && < 0.6 exposed-modules: Control.Exception.Lens@@ -193,6 +196,7 @@ Data.HashSet.Lens Data.IntSet.Lens Data.List.Lens+ Data.List.Split.Lens Data.Monoid.Lens Data.Sequence.Lens Data.Set.Lens@@ -201,7 +205,12 @@ Data.Text.Lazy.Lens Data.Tree.Lens Data.Typeable.Lens+ Data.Vector.Lens+ Data.Vector.Generic.Lens + other-modules:+ Control.Lens.Unsafe+ if flag(template-haskell) build-depends: template-haskell >= 2.4 && < 2.9 exposed-modules: Control.Lens.TH Language.Haskell.TH.Lens@@ -310,6 +319,22 @@ benchmark alongside type: exitcode-stdio-1.0 main-is: alongside.hs+ build-depends:+ base,+ comonad,+ comonads-fd,+ criterion,+ deepseq,+ ghc-prim,+ lens,+ transformers+ ghc-options: -w -O2 -threaded -fdicts-cheap -funbox-strict-fields+ hs-source-dirs: benchmarks++-- Basic benchmarks for the uniplate-style combinators+benchmark unsafe+ type: exitcode-stdio-1.0+ main-is: unsafe.hs build-depends: base, comonad,
src/Control/Lens.hs view
@@ -41,7 +41,7 @@ -- -- <http://github.com/ekmett/lens/wiki> ----- <<http://github.com/ekmett/lens/wiki/images/Hierarchy-3.2.png>>+-- <<http://github.com/ekmett/lens/wiki/images/Hierarchy-3.3.png>> ---------------------------------------------------------------------------- module Control.Lens ( module Control.Lens.Type
src/Control/Lens/Action.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE MultiParamTypeClasses #-} -----------------------------------------------------------------------------@@ -30,6 +31,7 @@ import Control.Applicative import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Monad.Trans.Class -- $setup@@ -58,12 +60,12 @@ -- -- > perform = flip (^!) perform :: Monad m => Acting m a s t a b -> s -> m a-perform l = getEffect . l (Effect . return)+perform l = getEffect# (l (effect# return)) {-# INLINE perform #-} -- | Perform an 'Action' and modify the result. performs :: Monad m => Acting m e s t a b -> (a -> e) -> s -> m e-performs l f = getEffect . l (Effect . return . f)+performs l f = getEffect# (l (effect# (return . f))) -- | Perform an 'Action' --@@ -71,7 +73,7 @@ -- hello -- world (^!) :: Monad m => s -> Acting m a s t a b -> m a-a ^! l = getEffect (l (Effect . return) a)+a ^! l = getEffect (l (effect# return) a) {-# INLINE (^!) #-} -- | Construct an 'Action' from a monadic side-effect
src/Control/Lens/Fold.hs view
@@ -81,6 +81,7 @@ import Control.Applicative.Backwards import Control.Lens.Getter import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Lens.Type import Control.Monad import Data.Foldable as Foldable@@ -183,8 +184,8 @@ {-# INLINE filtered #-} -- | This allows you to traverse the elements of a 'Control.Lens.Traversal.Traversal' or 'Fold' in the opposite order.--- This will demote an 'Control.Lens.IndexedTraversal.IndexedTraversal' or 'Control.Lens.IndexedFold.IndexedFold' to a regular 'Control.Lens.Traversal.Traversal' or 'Fold';--- to preserve the indices, use 'Control.Lens.IndexedFold.ibackwards' instead.+-- This will demote an 'Control.Lens.IndexedTraversal.IndexedTraversal' or 'Control.Lens.IndexedFold.IndexedFold' to a regular 'Control.Lens.Traversal.Traversal' or 'Fold',+-- repectively; to preserve the indices, use 'Control.Lens.IndexedFold.ibackwards' instead. -- -- Note: 'backwards' should have no impact on a 'Getter', 'Control.Lens.Setter.Setter', 'Lens' or 'Control.Lens.Iso.Iso'. --@@ -336,6 +337,7 @@ -- @ (^..) :: s -> Getting [a] s t a b -> [a] s ^.. l = foldMapOf l return s+{-# INLINE (^..) #-} -- | Returns 'True' if every target of a 'Fold' is 'True'. --
src/Control/Lens/Getter.hs view
@@ -67,6 +67,7 @@ ) where import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Monad.Reader.Class as Reader import Control.Monad.State.Class as State
src/Control/Lens/IndexedFold.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-}@@ -45,6 +46,17 @@ , ibackwards , itakingWhile , idroppingWhile+ , isplitting+ , isplittingOn+ , isplittingOneOf+ , isplittingWhen+ , iendingBy+ , iendingByOneOf+ , iwordingBy+ , iliningBy+ , ichunkingOf+ , isplittingPlaces+ , isplittingPlacesBlanks -- * Storing Indexed Folds , ReifiedIndexedFold(..)@@ -52,12 +64,16 @@ import Control.Applicative import Control.Applicative.Backwards+import Data.Traversable (traverse) import Control.Lens.Indexed import Control.Lens.IndexedGetter import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Lens.Type+import Control.Lens.Fold (toListOf) import Control.Monad import Data.Monoid+import Data.List.Split ------------------------------------------------------------------------------ -- Indexed Folds@@ -81,7 +97,7 @@ -- 'ifoldMapOf' :: 'Monoid' m => 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i a s -> (i -> s -> m) -> a -> m -- @ ifoldMapOf :: IndexedGetting i m s t a b -> (i -> a -> m) -> s -> m-ifoldMapOf l f = runAccessor . withIndex l (\i -> Accessor . f i)+ifoldMapOf l f = runAccessor# (withIndex l (\i -> accessor# (f i))) {-# INLINE ifoldMapOf #-} -- |@@ -99,7 +115,7 @@ -- 'ifoldrOf' :: 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i s a -> (i -> a -> r -> r) -> r -> s -> r -- @ ifoldrOf :: IndexedGetting i (Endo r) s t a b -> (i -> a -> r -> r) -> r -> s -> r-ifoldrOf l f z t = appEndo (ifoldMapOf l (\i -> Endo . f i) t) z+ifoldrOf l f z t = appEndo (ifoldMapOf l (\i -> endo# (f i)) t) z {-# INLINE ifoldrOf #-} -- |@@ -117,7 +133,7 @@ -- 'ifoldlOf' :: 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i s a -> (i -> r -> a -> r) -> r -> s -> r -- @ ifoldlOf :: IndexedGetting i (Dual (Endo r)) s t a b -> (i -> r -> a -> r) -> r -> s -> r-ifoldlOf l f z t = appEndo (getDual (ifoldMapOf l (\i -> Dual . Endo . flip (f i)) t)) z+ifoldlOf l f z t = appEndo (getDual (ifoldMapOf l (\i -> dual# (endo# (flip (f i)))) t)) z {-# INLINE ifoldlOf #-} -- |@@ -135,7 +151,7 @@ -- 'ianyOf' :: 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i s a -> (i -> a -> 'Bool') -> s -> 'Bool' -- @ ianyOf :: IndexedGetting i Any s t a b -> (i -> a -> Bool) -> s -> Bool-ianyOf l f = getAny . ifoldMapOf l (\i -> Any . f i)+ianyOf l f = getAny# (ifoldMapOf l (\i -> any# (f i))) {-# INLINE ianyOf #-} -- |@@ -153,7 +169,7 @@ -- 'iallOf' :: 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i s a -> (i -> a -> 'Bool') -> s -> 'Bool' -- @ iallOf :: IndexedGetting i All s t a b -> (i -> a -> Bool) -> s -> Bool-iallOf l f = getAll . ifoldMapOf l (\i -> All . f i)+iallOf l f = getAll# (ifoldMapOf l (\i -> all# (f i))) {-# INLINE iallOf #-} -- |@@ -170,7 +186,7 @@ -- 'itraverseOf_' :: 'Applicative' f => 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i s a -> (i -> a -> f r) -> s -> f () -- @ itraverseOf_ :: Functor f => IndexedGetting i (Traversed f) s t a b -> (i -> a -> f r) -> s -> f ()-itraverseOf_ l f = getTraversed . ifoldMapOf l (\i -> Traversed . void . f i)+itraverseOf_ l f = getTraversed# (ifoldMapOf l (\i -> traversed# (void . f i))) {-# INLINE itraverseOf_ #-} -- |@@ -208,7 +224,7 @@ -- 'imapMOf_' :: 'Monad' m => 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' i s a -> (i -> a -> m r) -> s -> m () -- @ imapMOf_ :: Monad m => IndexedGetting i (Sequenced m) s t a b -> (i -> a -> m r) -> s -> m ()-imapMOf_ l f = getSequenced . ifoldMapOf l (\i -> Sequenced . liftM skip . f i)+imapMOf_ l f = getSequenced# (ifoldMapOf l (\i -> sequenced# (liftM skip . f i))) {-# INLINE imapMOf_ #-} skip :: a -> ()@@ -271,7 +287,7 @@ -- 'ifindOf' :: 'Control.Lens.IndexedTraversal.SimpleIndexedTraversal' s a -> (i -> a -> 'Bool') -> s -> 'Maybe' (i, a) -- @ ifindOf :: IndexedGetting i (First (i, a)) s t a b -> (i -> a -> Bool) -> s -> Maybe (i, a)-ifindOf l p = getFirst . ifoldMapOf l step where+ifindOf l p = getFirst# (ifoldMapOf l step) where step i a | p i a = First $ Just (i, a) | otherwise = First Nothing@@ -373,7 +389,7 @@ -- 'withIndicesOf' :: 'SimpleIndexedTraversal' i s a -> 'Fold' s (i, a) -- @ ----- All 'Fold' operations are safe, and comply with the laws. However,+-- All 'Fold' operations are safe, and comply with the laws. However: -- -- Passing this an 'IndexedTraversal' will still allow many -- 'Traversal' combinators to type check on the result, but the result@@ -415,7 +431,7 @@ -- | Reverse the order of the elements of an 'IndexedFold' or 'Control.Lens.IndexedTraversal.IndexedTraversal'. -- This has no effect on an 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter', or 'Control.Lens.IndexedSetter.IndexedSetter'. ibackwards :: Indexed i k => Index i (a -> (Backwards f) b) (s -> (Backwards f) t) -> k (a -> f b) (s -> f t)-ibackwards l = index $ \ f -> fmap forwards . withIndex l $ \ i -> Backwards . f i+ibackwards l = index $ \ f -> fmap forwards . withIndex l $ \ i -> backwards# (f i) {-# INLINE ibackwards #-} -- | Obtain an 'IndexedFold' by taking elements from another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' while a predicate holds.@@ -432,8 +448,122 @@ => (i -> a -> Bool) -> IndexedGetting i (Endo (f s, f s)) s s a a -> k (a -> f a) (s -> f s)-idroppingWhile p l = index $ \f -> fst . ifoldrOf l (\i a r -> let s = f i a *> snd r in if p i a then (fst r, s) else (s, s)) (noEffect, noEffect)+idroppingWhile p l = index $ \ f -> fst . ifoldrOf l (\i a r -> let s = f i a *> snd r in if p i a then (fst r, s) else (s, s)) (noEffect, noEffect) {-# INLINE idroppingWhile #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' according to the given splitting strategy.+--+-- @+-- 'isplitting' :: 'Splitter' (i, a) -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+isplitting :: (Applicative f, Gettable f, Indexed [i] k) => Splitter (i, a) -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+isplitting s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . split s . toListOf (withIndicesOf l)+{-# INLINE isplitting #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' on the given delimiter.+--+-- Equivalent to @'isplitting' '.' 'dropDelims' '.' 'onSublist'@.+--+-- @+-- 'isplittingOn' :: ('Eq' i, 'Eq' a) => [(i, a)] -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+isplittingOn :: (Applicative f, Gettable f, Indexed [i] k, Eq i, Eq a) => [(i, a)] -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+isplittingOn s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . splitOn s . toListOf (withIndicesOf l)+{-# INLINE isplittingOn #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' on any of the given elements.+--+-- Equivalent to @'isplitting' '.' 'dropDelims' '.' 'oneOf'@.+--+-- @+-- 'isplittingOneOf' :: ('Eq' i, 'Eq' a) => [(i, a)] -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+isplittingOneOf :: (Applicative f, Gettable f, Indexed [i] k, Eq i, Eq a) => [(i, a)] -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+isplittingOneOf s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . splitOneOf s . toListOf (withIndicesOf l)+{-# INLINE isplittingOneOf #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' on elements satisfying the given predicate.+--+-- Equivalent to @'isplitting' '.' 'dropDelims' '.' 'whenElt' '.' 'uncurry'@.+--+-- @+-- 'isplittingWhen' :: (i -> a -> 'Bool') -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+isplittingWhen :: (Applicative f, Gettable f, Indexed [i] k) => (i -> a -> Bool) -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+isplittingWhen s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . splitWhen (uncurry s) . toListOf (withIndicesOf l)+{-# INLINE isplittingWhen #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into chunks terminated by the given delimiter.+--+-- Equivalent to @'isplitting' '.' 'dropDelims' '.' 'onSublist'@.+--+-- @+-- 'iendingBy' :: ('Eq' i, 'Eq' a) => [(i, a)] -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+iendingBy :: (Applicative f, Gettable f, Indexed [i] k, Eq i, Eq a) => [(i, a)] -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+iendingBy s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . endBy s . toListOf (withIndicesOf l)+{-# INLINE iendingBy #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into chunks terminated by any of the given elements.+--+-- Equivalent to @'isplitting' '.' 'dropFinalBlank' '.' 'dropDelims' '.' 'oneOf'@.+--+-- @+-- 'iendingByOneOf' :: ('Eq' i, 'Eq' a) => [(i, a)] -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+iendingByOneOf :: (Applicative f, Gettable f, Indexed [i] k, Eq i, Eq a) => [(i, a)] -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+iendingByOneOf s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . endByOneOf s . toListOf (withIndicesOf l)+{-# INLINE iendingByOneOf #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into "words", with word boundaries indicated by the given predicate.+--+-- Equivalent to @'isplitting' '.' 'dropBlanks' '.' 'dropDelims' '.' 'whenElt' '.' 'uncurry'@.+--+-- @+-- 'iwordingBy' :: (i -> a -> 'Bool') -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+iwordingBy :: (Applicative f, Gettable f, Indexed [i] k) => (i -> a -> Bool) -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+iwordingBy s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . wordsBy (uncurry s) . toListOf (withIndicesOf l)+{-# INLINE iwordingBy #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into "lines", with line boundaries indicated by the given predicate.+--+-- Equivalent to @'isplitting' '.' 'dropFinalBlank' '.' 'dropDelims' '.' 'whenElt' '.' 'uncurry'@.+--+-- @+-- 'iliningBy' :: (i -> a -> 'Bool') -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+iliningBy :: (Applicative f, Gettable f, Indexed [i] k) => (i -> a -> Bool) -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+iliningBy s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . linesBy (uncurry s) . toListOf (withIndicesOf l)+{-# INLINE iliningBy #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into length-@n@ pieces.+--+-- @+-- 'ichunkingOf' :: 'Int' -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+ichunkingOf :: (Applicative f, Gettable f, Indexed [i] k) => Int -- ^ @n@+ -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+ichunkingOf s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . chunksOf s . toListOf (withIndicesOf l)+{-# INLINE ichunkingOf #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into chunks of the given lengths.+--+-- @+-- 'isplittingPlaces' :: 'Integral' n => [n] -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+isplittingPlaces :: (Applicative f, Gettable f, Indexed [i] k, Integral n) => [n] -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+isplittingPlaces s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . splitPlaces s . toListOf (withIndicesOf l)+{-# INLINE isplittingPlaces #-}++-- | Obtain an 'IndexedFold' by splitting another 'IndexedFold', 'Control.Lens.IndexedLens.IndexedLens', 'IndexedGetter' or 'Control.Lens.IndexedTraversal.IndexedTraversal' into chunks of the given lengths. Unlike 'isplittingPlaces', the output 'IndexedFold' will always be the same length as the first input argument.+--+-- @+-- 'isplittingPlacesBlanks' :: 'Integral' n => [n] -> 'IndexedFold' i s a -> 'IndexedFold' [i] s [a]+-- @+isplittingPlacesBlanks :: (Applicative f, Gettable f, Indexed [i] k, Integral n) => [n] -> IndexedGetting i [(i, a)] s s a a -> k ([a] -> f [a]) (s -> f s)+isplittingPlacesBlanks s l = index $ \ f -> coerce . traverse (uncurry f . unzip) . splitPlacesBlanks s . toListOf (withIndicesOf l)+{-# INLINE isplittingPlacesBlanks #-} ------------------------------------------------------------------------------ -- Reifying Indexed Folds
src/Control/Lens/IndexedLens.hs view
@@ -30,6 +30,7 @@ -- * Common Indexed Lenses , At(..) , Contains(..)+ , resultAt -- * Indexed Lens Combinators , (%%@~) , (<%@~)@@ -186,6 +187,15 @@ instance (Eq k, Hashable k) => Contains k (HashSet k) where contains k = index $ \ f s -> (\b -> if b then HashSet.insert k s else HashSet.delete k s) <$> f k (HashSet.member k s) {-# INLINE contains #-}++-- | This lens can be used to change the result of a function but only where+-- the arguments match the key given.+--+-- >>> let f = (+1) % resultAt 3 .~ 8 in (f 2, f 3)+-- (3,8)+resultAt :: Eq e => e -> SimpleIndexedLens e (e -> a) a+resultAt e = index $ \ g f -> (\a' e' -> if e == e' then a' else f e') <$> g e (f e)+{-# INLINE resultAt #-} ------------------------------------------------------------------------------ -- Reifying Indexed Lenses
src/Control/Lens/IndexedSetter.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -28,9 +29,9 @@ , SimpleReifiedIndexedSetter ) where -import Control.Applicative import Control.Lens.Indexed import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Lens.Type import Control.Monad.State.Class as State @@ -58,7 +59,7 @@ -- 'imapOf' :: 'Control.Lens.IndexedTraversal.IndexedTraversal' i s t a b -> (i -> a -> b) -> s -> t -- @ imapOf :: Overloaded (Index i) Mutator s t a b -> (i -> a -> b) -> s -> t-imapOf l f = runMutator . withIndex l (\i -> Mutator . f i)+imapOf l f = runMutator# (withIndex l (\i -> mutator# (f i))) {-# INLINE imapOf #-} -- | Map with index. This is an alias for 'imapOf'.@@ -73,7 +74,7 @@ -- 'iover' :: 'Control.Lens.IndexedTraversal.IndexedTraversal' i s t a b -> (i -> a -> b) -> s -> t -- @ iover :: Overloaded (Index i) Mutator s t a b -> (i -> a -> b) -> s -> t-iover l f = runMutator . withIndex l (\i -> Mutator . f i)+iover l f = runMutator# (withIndex l (\i -> mutator# (f i))) {-# INLINE iover #-} -- | Build an 'IndexedSetter' from an 'imap'-like function.@@ -95,7 +96,7 @@ -- Another way to view 'sets' is that it takes a \"semantic editor combinator\" -- and transforms it into a 'Setter'. isets :: ((i -> a -> b) -> s -> t) -> IndexedSetter i s t a b-isets f = index $ \ g -> pure . f (\i -> untainted . g i)+isets f = index $ \ g -> tainted# (f (\i -> untainted# (g i))) {-# INLINE isets #-} -- | Adjust every target of an 'IndexedSetter', 'Control.Lens.IndexedLens.IndexedLens' or 'Control.Lens.IndexedTraversal.IndexedTraversal'@@ -113,7 +114,7 @@ -- ('%@~') :: 'Control.Lens.IndexedTraversal.IndexedTraversal' i s t a b -> (i -> a -> b) -> s -> t -- @ (%@~) :: Overloaded (Index i) Mutator s t a b -> (i -> a -> b) -> s -> t-l %@~ f = runMutator . withIndex l (\i -> Mutator . f i)+l %@~ f = runMutator# (withIndex l (\i -> mutator# (f i))) {-# INLINE (%@~) #-} -- | Adjust every target in the current state of an 'IndexedSetter', 'Control.Lens.IndexedLens.IndexedLens' or 'Control.Lens.IndexedTraversal.IndexedTraversal'
src/Control/Lens/IndexedTraversal.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE ScopedTypeVariables #-} #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704 {-# LANGUAGE Trustworthy #-}@@ -32,6 +33,7 @@ , traverseAt , iwhereOf , value+ , ignored , TraverseMin(..) , TraverseMax(..) @@ -60,6 +62,7 @@ import Data.Traversable import Data.IntMap as IntMap import Data.Map as Map+import Data.Void -- $setup -- >>> import Control.Lens@@ -209,6 +212,16 @@ value :: (k -> Bool) -> SimpleIndexedTraversal k (k, v) v value p = index $ \ f kv@(k,v) -> if p k then (,) k <$> f k v else pure kv {-# INLINE value #-}++-- | This is the trivial empty traversal.+--+-- @'ignored' :: 'IndexedTraversal' 'Void' s s a b+--+-- @'ignored' ≡ 'const' 'pure'@+ignored :: forall s a b k f. (Indexed Void k, Applicative f) => Overloaded k f s s a b+ignored = index $ \ (_ :: Void -> a -> f b) s -> pure s :: f s+{-# INLINE ignored #-}+ -- | Allows 'IndexedTraversal' the value at the smallest index. class Ord k => TraverseMin k m | m -> k where
src/Control/Lens/Internal.hs view
@@ -45,174 +45,6 @@ import Data.Traversable import Unsafe.Coerce -const# :: (a -> b) -> a -> Const b r-const# = unsafeCoerce--getConst# :: (a -> Const b r) -> a -> b-getConst# = unsafeCoerce--zipList# :: (a -> [b]) -> a -> ZipList b-zipList# = unsafeCoerce--getZipList# :: (a -> ZipList b) -> a -> [b]-getZipList# = unsafeCoerce--wrapMonad# :: (a -> m b) -> a -> WrappedMonad m b-wrapMonad# = unsafeCoerce--unwrapMonad# :: (a -> WrappedMonad m b) -> a -> m b-unwrapMonad# = unsafeCoerce--last# :: (a -> Maybe b) -> a -> Last b-last# = unsafeCoerce--getLast# :: (a -> Last b) -> a -> Maybe b-getLast# = unsafeCoerce--first# :: (a -> Maybe b) -> a -> First b-first# = unsafeCoerce--getFirst# :: (a -> First b) -> a -> Maybe b-getFirst# = unsafeCoerce--product# :: (a -> b) -> a -> Product b-product# = unsafeCoerce--getProduct# :: (a -> Product b) -> a -> b-getProduct# = unsafeCoerce--sum# :: (a -> b) -> a -> Sum b-sum# = unsafeCoerce--getSum# :: (a -> Sum b) -> a -> b-getSum# = unsafeCoerce--any# :: (a -> Bool) -> a -> Any-any# = unsafeCoerce--getAny# :: (a -> Any) -> a -> Bool-getAny# = unsafeCoerce--all# :: (a -> Bool) -> a -> All-all# = unsafeCoerce--getAll# :: (a -> All) -> a -> Bool-getAll# = unsafeCoerce--dual# :: (a -> b) -> a -> Dual b-dual# = unsafeCoerce--getDual# :: (a -> Dual b) -> a -> b-getDual# = unsafeCoerce--endo# :: (a -> b -> b) -> a -> Endo b-endo# = unsafeCoerce--appEndo# :: (a -> Endo b) -> a -> b -> b-appEndo# = unsafeCoerce--may# :: (a -> Maybe b) -> a -> May b-may# = unsafeCoerce--getMay# :: (a -> May b) -> a -> Maybe b-getMay# = unsafeCoerce--folding# :: (a -> f b) -> a -> Folding f b-folding# = unsafeCoerce--getFolding# :: (a -> Folding f b) -> a -> f b-getFolding# = unsafeCoerce--effect# :: (a -> m r) -> a -> Effect m r b-effect# = unsafeCoerce--getEffect# :: (a -> Effect m r b) -> a -> m r-getEffect# = unsafeCoerce--effectRWS# :: (a -> st -> m (s, st, w)) -> a -> EffectRWS w st m s b-effectRWS# = unsafeCoerce--getEffectRWS# :: (a -> EffectRWS w st m s b) -> a -> st -> m (s, st, w)-getEffectRWS# = unsafeCoerce--accessor# :: (a -> r) -> a -> Accessor r b-accessor# = unsafeCoerce--runAccessor# :: (a -> Accessor r b) -> a -> r-runAccessor# = unsafeCoerce--err# :: (a -> Either e b) -> a -> Err e b-err# = unsafeCoerce--getErr# :: (a -> Err e b) -> a -> Either e b-getErr# = unsafeCoerce--traversed# :: (a -> f ()) -> a -> Traversed f-traversed# = unsafeCoerce--getTraversed# :: (a -> Traversed f) -> a -> f ()-getTraversed# = unsafeCoerce--sequenced# :: (a -> f ()) -> a -> Sequenced f-sequenced# = unsafeCoerce--getSequenced# :: (a -> Sequenced f) -> a -> f ()-getSequenced# = unsafeCoerce--focusing# :: (a -> m (s, b)) -> a -> Focusing m s b-focusing# = unsafeCoerce--unfocusing# :: (a -> Focusing m s b) -> a -> m (s, b)-unfocusing# = unsafeCoerce--focusingWith# :: (a -> m (s, b, w)) -> a -> FocusingWith w m s b-focusingWith# = unsafeCoerce--unfocusingWith# :: (a -> FocusingWith w m s b) -> a -> m (s, b, w)-unfocusingWith# = unsafeCoerce--focusingPlus# :: (a -> k (s, w) b) -> a -> FocusingPlus w k s b-focusingPlus# = unsafeCoerce--unfocusingPlus# :: (a -> FocusingPlus w k s b) -> a -> k (s, w) b-unfocusingPlus# = unsafeCoerce--focusingOn# :: (a -> k (f s) b) -> a -> FocusingOn f k s b-focusingOn# = unsafeCoerce--unfocusingOn# :: (a -> FocusingOn f k s b) -> a -> k (f s) b-unfocusingOn# = unsafeCoerce--focusingMay# :: (a -> k (May s) b) -> a -> FocusingMay k s b-focusingMay# = unsafeCoerce--unfocusingMay# :: (a -> FocusingMay k s b) -> a -> k (May s) b-unfocusingMay# = unsafeCoerce--focusingErr# :: (a -> k (Err e s) b) -> a -> FocusingErr e k s b-focusingErr# = unsafeCoerce--unfocusingErr# :: (a -> FocusingErr e k s b) -> a -> k (Err e s) b-unfocusingErr# = unsafeCoerce--bazaar# :: (forall f. Applicative f => a -> (c -> f d) -> f t) -> a -> Bazaar c d t-bazaar# = unsafeCoerce--runBazaar# :: Applicative f => (a -> Bazaar c d t) -> a -> (c -> f d) -> f t-runBazaar# = unsafeCoerce--mutator# :: (a -> b) -> a -> Mutator b-mutator# = unsafeCoerce--runMutator# :: (a -> Mutator b) -> a -> b-runMutator# = unsafeCoerce--backwards# :: (a -> f b) -> a -> Backwards f b-backwards# = unsafeCoerce--forwards# :: (a -> Backwards f b) -> a -> f b-forwards# = unsafeCoerce- ----------------------------------------------------------------------------- -- Functors -----------------------------------------------------------------------------@@ -586,14 +418,19 @@ class Applicative f => Settable f where untainted :: f a -> a - untainted# :: (b -> f a) -> b -> a+ untainted# :: (a -> f b) -> a -> b untainted# f = untainted . f + tainted# :: (a -> b) -> a -> f b+ tainted# f = pure . f+ -- | so you can pass our a 'Control.Lens.Setter.Setter' into combinators from other lens libraries instance Settable Identity where untainted = runIdentity untainted# = unsafeCoerce {-# INLINE untainted #-}+ tainted# = unsafeCoerce+ {-# INLINE tainted# #-} -- | 'Control.Lens.Fold.backwards' instance Settable f => Settable (Backwards f) where@@ -610,6 +447,8 @@ untainted = runMutator untainted# = unsafeCoerce {-# INLINE untainted #-}+ tainted# = unsafeCoerce+ {-# INLINE tainted# #-} -- | 'Mutator' is just a renamed 'Identity' functor to give better error -- messages when someone attempts to use a getter as a setter.@@ -691,7 +530,7 @@ fmap f (Level n ls a rs) = Level n (f <$> ls) (f a) (f <$> rs) instance Foldable Level where- foldMap f = foldMap f . rezipLevel+ foldMap f (Level _ ls a rs) = foldMap f (Prelude.reverse ls) <> f a <> foldMap f rs instance Traversable Level where traverse f (Level n ls a rs) = Level n <$> forwards (traverse (Backwards . f) ls) <*> f a <*> traverse f rs
src/Control/Lens/Iso.hs view
@@ -14,7 +14,6 @@ ( -- * Isomorphism Lenses Iso- , (:<->) , iso , isos , ala@@ -28,6 +27,7 @@ -- ** Common Isomorphisms , _const , identity+ , simple -- * Storing Isomorphisms , ReifiedIso(..) -- * Simplicity@@ -48,13 +48,11 @@ -- $setup -- >>> import Control.Lens -infixr 0 :<->- ----------------------------------------------------------------------------- -- Isomorphisms families as Lenses ----------------------------------------------------------------------------- --- | Isomorphim families can be composed with other lenses using either ('.') and 'id'+-- | Isomorphism families can be composed with other lenses using either ('.') and 'id' -- from the Prelude or from Control.Category. However, if you compose them -- with each other using ('.') from the Prelude, they will be dumbed down to a -- mere 'Lens'.@@ -71,8 +69,6 @@ -- @type 'SimpleIso' = 'Control.Lens.Type.Simple' 'Iso'@ type SimpleIso s a = Iso s s a a --- | An commonly used infix alias for @'Control.Lens.Type.Simple' 'Iso'@-type s :<-> a = Iso s s a a -- | Build an isomorphism family from two pairs of inverse functions --@@ -81,7 +77,6 @@ -- 'view' ('from' ('isos' sa as tb bt)) ≡ as -- 'set' ('isos' sa as tb bt) ab ≡ bt '.' ab '.' sa -- 'set' ('from' ('isos' ac ca bd db')) ab ≡ bd '.' ab '.' ca--- 'set' ('from' ('isos' sa as tb bt')) s t ≡ tb '.' st '.' as -- @ -- -- @isos :: (s -> a) -> (a -> s) -> (t -> b) -> (b -> t) -> 'Iso' s t a b@@@ -156,6 +151,14 @@ _const :: Iso a b (Const a c) (Const b d) _const = isos Const getConst Const getConst {-# INLINE _const #-}+++-- | Composition with this isomorphism is occasionally useful when your 'Lens',+-- 'Control.Lens.Traversal.Traversal' or 'Iso' has a constraint on an unused+-- argument to force that argument to agree with the+-- type of a used argument and avoid @ScopedTypeVariables@ or other ugliness.+simple :: Iso a b a b+simple = isos id id id id ----------------------------------------------------------------------------- -- Reifying Isomorphisms
src/Control/Lens/Plated.hs view
@@ -90,6 +90,8 @@ import Control.Lens.Traversal import Control.Lens.Type import Data.Tree+import Data.Data+import Data.Data.Lens -- | A 'Plated' type is one where we know how to extract its immediate self-similar children. --@@ -182,7 +184,8 @@ -- -- The default definition finds no children. plate :: Simple Traversal a a- plate = ignored+ default plate :: Data a => Simple Traversal a a+ plate = uniplate instance Plated [a] where plate f (x:xs) = (x:) <$> f xs@@ -786,7 +789,7 @@ -- 'partsOf' :: 'Simple' 'Traversal' s a -> 'Simple' 'Lens' s [a] -- @ partsOf :: LensLike (Bazaar a a) s t a a -> Lens s t [a] [a]-partsOf l f a = outs b <$> f (ins b) where b = l sell a+partsOf l f s = outs b <$> f (ins b) where b = l sell s {-# INLINE partsOf #-} -- | 'unsafePartsOf' turns a 'Traversal' into a @uniplate@ (or @biplate@) family.@@ -806,7 +809,7 @@ -- 'unsafePartsOf' :: 'Traversal' s t a b -> 'Lens' s t [a] [b] -- @ unsafePartsOf :: LensLike (Bazaar a b) s t a b -> Lens s t [a] [b]-unsafePartsOf l f a = unsafeOuts b <$> f (ins b) where b = l sell a+unsafePartsOf l f s = unsafeOuts b <$> f (ins b) where b = l sell s {-# INLINE unsafePartsOf #-} ------------------------------------------------------------------------------@@ -836,20 +839,20 @@ ------------------------------------------------------------------------------- ins :: Bazaar a b t -> [a]-ins (Bazaar m) = getConst (m (Const . return))+ins = toListOf bazaar {-# INLINE ins #-} -unsafeUncons :: [a] -> (a,[a])-unsafeUncons ~(a:as) = (a,as)-{-# INLINE unsafeUncons #-}+unconsWithDefault :: a -> [a] -> (a,[a])+unconsWithDefault d [] = (d,[])+unconsWithDefault _ (x:xs) = (x,xs)+{-# INLINE unconsWithDefault #-} outs :: Bazaar a a t -> [a] -> t-outs (Bazaar m) = evalState $ m $ \c -> state $ \cs -> case cs of- [] -> (c,[])- (d:ds) -> (d,ds)+outs = evalState . bazaar (\oldVal -> state (unconsWithDefault oldVal)) {-# INLINE outs #-} unsafeOuts :: Bazaar a b t -> [b] -> t-unsafeOuts (Bazaar m) = evalState (m $ \_ -> state unsafeUncons)+unsafeOuts = evalState . bazaar (\_ -> state (unconsWithDefault fakeVal))+ where fakeVal = error "unsafePartsOf: not enough elements were supplied" {-# INLINE unsafeOuts #-}
src/Control/Lens/Representable.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE FlexibleContexts #-} -----------------------------------------------------------------------------@@ -89,10 +90,12 @@ import Control.Lens.Type import Control.Lens.Getter import Control.Lens.Indexed-import Control.Lens.IndexedSetter import Control.Lens.IndexedFold+import Control.Lens.IndexedLens+import Control.Lens.IndexedSetter import Control.Lens.IndexedTraversal import Control.Lens.Internal+import Control.Lens.Unsafe import Data.Foldable as Foldable import Data.Functor.Identity import Data.Monoid@@ -299,12 +302,12 @@ -- | An 'IndexedSetter' that walks an 'Representable' 'Functor' using a 'Path' for an index. rmapped :: Representable f => IndexedSetter (Path f) (f a) (f b) a b-rmapped = index $ \f -> pure . rmap (\i -> untainted . f (Path i))+rmapped = index $ \f -> tainted# (rmap (\i -> untainted# (f (Path i)))) {-# INLINE rmapped #-} -- | An 'IndexedFold' that walks an 'Foldable' 'Representable' 'Functor' using a 'Path' for an index. rfolded :: (Representable f, Foldable f) => IndexedFold (Path f) (f a) a-rfolded = index $ \f -> coerce . getFolding . rfoldMap (\i -> Folding . f (Path i))+rfolded = index $ \f -> coerce . getFolding . rfoldMap (\i -> folding# (f (Path i))) {-# INLINE rfolded #-} -- | An 'IndexedTraversal' for a 'Traversable' 'Representable' 'Functor'.
src/Control/Lens/Setter.hs view
@@ -30,6 +30,7 @@ , sets -- * Common Setters , mapped+ , lifted -- * Functional Combinators , over , mapOf@@ -54,8 +55,9 @@ , Mutator ) where -import Control.Applicative import Control.Lens.Internal+import Control.Lens.Unsafe+import Control.Monad (liftM) import Control.Monad.State.Class as State -- $setup@@ -72,7 +74,7 @@ -- | -- The only 'Control.Lens.Type.Lens'-like law that can apply to a 'Setter' @l@ is that ----- @'set' l y ('set' l x a) ≡ 'set' l x a@+-- @'set' l y ('set' l x a) ≡ 'set' l y a@ -- -- You can't 'view' a 'Setter' in general, so the other two laws are irrelevant. --@@ -149,6 +151,21 @@ mapped = sets fmap {-# INLINE mapped #-} +-- | This setter can be used to modify all of the values in a 'Monad'.+--+-- You sometimes have to use this, rather than 'mapped', because due to+-- temporary insanity 'Functor' is not a superclass of 'Monad'.+--+-- @+-- 'liftM' ≡ 'over' 'lifted'+-- @+--+-- >>> over lifted (+1) [1,2,3]+-- [2,3,4]+lifted :: Monad m => Setter (m a) (m b) a b+lifted = sets liftM+{-# INLINE lifted #-}+ -- | Build a Setter from a map-like function. -- -- Your supplied function @f@ is required to satisfy:@@ -168,7 +185,7 @@ -- Another way to view 'sets' is that it takes a \"semantic editor combinator\" -- and transforms it into a 'Setter'. sets :: ((a -> b) -> s -> t) -> Setter s t a b-sets f g = pure . f (untainted# g)+sets f g = tainted# (f (untainted# g)) {-# INLINE sets #-} -----------------------------------------------------------------------------
src/Control/Lens/Simple.hs view
@@ -15,14 +15,19 @@ module Control.Lens.Simple ( (:->) , (:=>)+ , (:<->) ) where import Control.Applicative+import Control.Lens.Iso -infixr 0 :=>, :->+infixr 0 :=>, :->, :<-> -- | This is a commonly used infix alias for a @'Control.Lens.Type.Simple' 'Control.Lens.Type.Lens'@. type s :-> a = forall f. Functor f => (a -> f a) -> s -> f s -- | This is a commonly-used infix alias for a @'Control.Lens.Type.Simple' 'Control.Lens.Traversal.Traversal'@. type s :=> a = forall f. Applicative f => (a -> f a) -> s -> f s++-- | This is a commonly-used infix alias for a @'Control.Lens.Type.Simple' 'Iso'@+type s :<-> a = Iso s s a a
src/Control/Lens/TH.hs view
@@ -209,6 +209,7 @@ -- | Rules for making an isomorphism from a data type isoRules :: LensRules isoRules = defaultRules+ % handleSingletons .~ True % singletonRequired .~ True % singletonAndField .~ True
src/Control/Lens/Traversal.hs view
@@ -41,10 +41,10 @@ -- * Common Traversals , Traversable(traverse)- , ignored , traverseLeft , traverseRight , both+ , beside , taking , dropping @@ -61,6 +61,7 @@ import Control.Applicative.Backwards import Control.Lens.Fold import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Lens.Type import Control.Monad.State.Class as State import Control.Monad.Trans.State.Lazy as Lazy@@ -300,15 +301,6 @@ -- Traversals ------------------------------------------------------------------------------ --- | This is the trivial empty traversal.------ @'ignored' :: 'Applicative' f => (a -> f b) -> s -> f s@------ @'ignored' ≡ 'const' 'pure'@-ignored :: Traversal s s a b-ignored _ = pure-{-# INLINE ignored #-}- -- | Traverse both parts of a tuple with matching types. -- -- >>> both *~ 10 $ (1,2)@@ -318,8 +310,16 @@ -- >>> ("hello","world")^.both -- "helloworld" both :: Traversal (a,a) (b,b) a b-both f (a,a') = (,) <$> f a <*> f a'+both f ~(a,a') = (,) <$> f a <*> f a' {-# INLINE both #-}++-- | Apply a different 'Traversal' or 'Control.Lens.Fold.Fold' to each side of a tuple.+--+-- >>> ("hello",["world","!!!"])^..beside id traverse+-- ["hello","world","!!!"]+beside :: Applicative f => LensLike f s t a b -> LensLike f s' t' a b -> LensLike f (s,s') (t,t') a b+beside l r f ~(s,s') = (,) <$> l f s <*> r f s'+{-# INLINE beside #-} -- | A traversal for tweaking the left-hand value of an 'Either': --
src/Control/Lens/Type.hs view
@@ -58,12 +58,9 @@ , Simple , lens- , simple , (%%~) , (%%=) - , resultAt- -- * Lateral Composition , choosing , chosen@@ -182,12 +179,6 @@ lens sa sbt afb s = sbt s <$> afb (sa s) {-# INLINE lens #-} --- | This is occasionally useful when your 'Lens' (or 'Control.Lens.Traversal.Traversal')--- has a constraint on an unused argument to force that argument to agree with the--- type of a used argument and avoid @ScopedTypeVariables@ or other ugliness.-simple :: SimpleLensLike f s a -> SimpleLensLike f s a-simple l = l- ------------------------------------------------------------------------------- -- LensLike -------------------------------------------------------------------------------@@ -270,15 +261,6 @@ ------------------------------------------------------------------------------- -- Common Lenses ----------------------------------------------------------------------------------- | This lens can be used to change the result of a function but only where--- the arguments match the key given.-resultAt :: Eq e => e -> Simple Lens (e -> a) a-resultAt e afa ea = go <$> afa a where- a = ea e- go a' e' | e == e' = a'- | otherwise = a-{-# INLINE resultAt #-} -- | Merge two lenses, getters, setters, folds or traversals. --
+ src/Control/Lens/Unsafe.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE MagicHash #-}+#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704+{-# LANGUAGE Trustworthy #-}+#endif++-----------------------------------------------------------------------------+-- |+-- Module : Control.Lens.Unsafe+-- Copyright : (C) 2012 Edward Kmett+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : Rank2Types+--+-- These horrible unexported combinators are useful for producing more+-- efficient core. See <https://github.com/ekmett/lens/issues/75>.+--+----------------------------------------------------------------------------+module Control.Lens.Unsafe+ ( const#, getConst#+ , zipList#, getZipList#+ , wrapMonad#, unwrapMonad#+ , last#, getLast#+ , first#, getFirst#+ , product#, getProduct#+ , sum#, getSum#+ , any#, getAny#+ , all#, getAll#+ , dual#, getDual#+ , endo#, appEndo#+ , may#, getMay#+ , folding#, getFolding#+ , effect#, getEffect#+ , effectRWS#, getEffectRWS#+ , accessor#, runAccessor#+ , err#, getErr#+ , traversed#, getTraversed#+ , sequenced#, getSequenced#+ , focusing#, unfocusing#+ , focusingWith#, unfocusingWith#+ , focusingPlus#, unfocusingPlus#+ , focusingOn#, unfocusingOn#+ , focusingMay#, unfocusingMay#+ , focusingErr#, unfocusingErr#+ , mutator#, runMutator#+ , backwards#, forwards#+ ) where++import Control.Applicative+import Control.Applicative.Backwards+import Control.Lens.Internal+import Data.Monoid+import Unsafe.Coerce++const# :: (a -> b) -> a -> Const b r+const# = unsafeCoerce++getConst# :: (a -> Const b r) -> a -> b+getConst# = unsafeCoerce++zipList# :: (a -> [b]) -> a -> ZipList b+zipList# = unsafeCoerce++getZipList# :: (a -> ZipList b) -> a -> [b]+getZipList# = unsafeCoerce++wrapMonad# :: (a -> m b) -> a -> WrappedMonad m b+wrapMonad# = unsafeCoerce++unwrapMonad# :: (a -> WrappedMonad m b) -> a -> m b+unwrapMonad# = unsafeCoerce++last# :: (a -> Maybe b) -> a -> Last b+last# = unsafeCoerce++getLast# :: (a -> Last b) -> a -> Maybe b+getLast# = unsafeCoerce++first# :: (a -> Maybe b) -> a -> First b+first# = unsafeCoerce++getFirst# :: (a -> First b) -> a -> Maybe b+getFirst# = unsafeCoerce++product# :: (a -> b) -> a -> Product b+product# = unsafeCoerce++getProduct# :: (a -> Product b) -> a -> b+getProduct# = unsafeCoerce++sum# :: (a -> b) -> a -> Sum b+sum# = unsafeCoerce++getSum# :: (a -> Sum b) -> a -> b+getSum# = unsafeCoerce++any# :: (a -> Bool) -> a -> Any+any# = unsafeCoerce++getAny# :: (a -> Any) -> a -> Bool+getAny# = unsafeCoerce++all# :: (a -> Bool) -> a -> All+all# = unsafeCoerce++getAll# :: (a -> All) -> a -> Bool+getAll# = unsafeCoerce++dual# :: (a -> b) -> a -> Dual b+dual# = unsafeCoerce++getDual# :: (a -> Dual b) -> a -> b+getDual# = unsafeCoerce++endo# :: (a -> b -> b) -> a -> Endo b+endo# = unsafeCoerce++appEndo# :: (a -> Endo b) -> a -> b -> b+appEndo# = unsafeCoerce++may# :: (a -> Maybe b) -> a -> May b+may# = unsafeCoerce++getMay# :: (a -> May b) -> a -> Maybe b+getMay# = unsafeCoerce++folding# :: (a -> f b) -> a -> Folding f b+folding# = unsafeCoerce++getFolding# :: (a -> Folding f b) -> a -> f b+getFolding# = unsafeCoerce++effect# :: (a -> m r) -> a -> Effect m r b+effect# = unsafeCoerce++getEffect# :: (a -> Effect m r b) -> a -> m r+getEffect# = unsafeCoerce++effectRWS# :: (a -> st -> m (s, st, w)) -> a -> EffectRWS w st m s b+effectRWS# = unsafeCoerce++getEffectRWS# :: (a -> EffectRWS w st m s b) -> a -> st -> m (s, st, w)+getEffectRWS# = unsafeCoerce++accessor# :: (a -> r) -> a -> Accessor r b+accessor# = unsafeCoerce++runAccessor# :: (a -> Accessor r b) -> a -> r+runAccessor# = unsafeCoerce++err# :: (a -> Either e b) -> a -> Err e b+err# = unsafeCoerce++getErr# :: (a -> Err e b) -> a -> Either e b+getErr# = unsafeCoerce++traversed# :: (a -> f ()) -> a -> Traversed f+traversed# = unsafeCoerce++getTraversed# :: (a -> Traversed f) -> a -> f ()+getTraversed# = unsafeCoerce++sequenced# :: (a -> f ()) -> a -> Sequenced f+sequenced# = unsafeCoerce++getSequenced# :: (a -> Sequenced f) -> a -> f ()+getSequenced# = unsafeCoerce++focusing# :: (a -> m (s, b)) -> a -> Focusing m s b+focusing# = unsafeCoerce++unfocusing# :: (a -> Focusing m s b) -> a -> m (s, b)+unfocusing# = unsafeCoerce++focusingWith# :: (a -> m (s, b, w)) -> a -> FocusingWith w m s b+focusingWith# = unsafeCoerce++unfocusingWith# :: (a -> FocusingWith w m s b) -> a -> m (s, b, w)+unfocusingWith# = unsafeCoerce++focusingPlus# :: (a -> k (s, w) b) -> a -> FocusingPlus w k s b+focusingPlus# = unsafeCoerce++unfocusingPlus# :: (a -> FocusingPlus w k s b) -> a -> k (s, w) b+unfocusingPlus# = unsafeCoerce++focusingOn# :: (a -> k (f s) b) -> a -> FocusingOn f k s b+focusingOn# = unsafeCoerce++unfocusingOn# :: (a -> FocusingOn f k s b) -> a -> k (f s) b+unfocusingOn# = unsafeCoerce++focusingMay# :: (a -> k (May s) b) -> a -> FocusingMay k s b+focusingMay# = unsafeCoerce++unfocusingMay# :: (a -> FocusingMay k s b) -> a -> k (May s) b+unfocusingMay# = unsafeCoerce++focusingErr# :: (a -> k (Err e s) b) -> a -> FocusingErr e k s b+focusingErr# = unsafeCoerce++unfocusingErr# :: (a -> FocusingErr e k s b) -> a -> k (Err e s) b+unfocusingErr# = unsafeCoerce++mutator# :: (a -> b) -> a -> Mutator b+mutator# = unsafeCoerce++runMutator# :: (a -> Mutator b) -> a -> b+runMutator# = unsafeCoerce++backwards# :: (a -> f b) -> a -> Backwards f b+backwards# = unsafeCoerce++forwards# :: (a -> Backwards f b) -> a -> f b+forwards# = unsafeCoerce+
src/Control/Lens/WithIndex.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} {-# LANGUAGE CPP #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE FlexibleInstances #-}@@ -63,6 +64,7 @@ import Control.Monad.Trans.State.Lazy as Lazy import Control.Lens.Fold import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Lens.Indexed import Control.Lens.IndexedSetter import Control.Lens.IndexedFold@@ -75,6 +77,8 @@ import Data.Monoid import Data.Sequence hiding (index) import Data.Traversable+import Data.Vector (Vector)+import qualified Data.Vector as V -- $setup -- >>> import Control.Lens@@ -132,7 +136,7 @@ -- -- @'Data.Foldable.foldr' ≡ 'ifoldr' '.' 'const'@ ifoldr :: (i -> a -> b -> b) -> b -> f a -> b- ifoldr f z t = appEndo (ifoldMap (\i -> Endo . f i) t) z+ ifoldr f z t = appEndo (ifoldMap (\i -> endo# (f i)) t) z -- | -- Left-associative fold of an indexed container with access to the index @i@.@@ -141,7 +145,7 @@ -- -- @'foldl' ≡ 'ifoldl' '.' 'const'@ ifoldl :: (i -> b -> a -> b) -> b -> f a -> b- ifoldl f z t = appEndo (getDual (ifoldMap (\i -> Dual . Endo . flip (f i)) t)) z+ ifoldl f z t = appEndo (getDual (ifoldMap (\i -> dual# (endo# (flip (f i)))) t)) z -- | /Strictly/ fold right over the elements of a structure with access to the index @i@. --@@ -170,7 +174,7 @@ -- | The 'IndexedFold' of a 'FoldableWithIndex' container. ifolded :: FoldableWithIndex i f => IndexedFold i (f a) a-ifolded = index $ \ f -> coerce . getFolding . ifoldMap (\i -> Folding . f i)+ifolded = index $ \ f -> coerce . getFolding . ifoldMap (\i -> folding# (f i)) {-# INLINE ifolded #-} -- | Obtain a 'Fold' by lifting an operation that returns a foldable result.@@ -187,7 +191,7 @@ -- -- @'any' = 'iany' '.' 'const'@ iany :: FoldableWithIndex i f => (i -> a -> Bool) -> f a -> Bool-iany f = getAny . ifoldMap (\i -> Any . f i)+iany f = getAny# (ifoldMap (\i -> any# (f i))) {-# INLINE iany #-} -- |@@ -197,7 +201,7 @@ -- -- @'all' ≡ 'iall' '.' 'const'@ iall :: FoldableWithIndex i f => (i -> a -> Bool) -> f a -> Bool-iall f = getAll . ifoldMap (\i -> All . f i)+iall f = getAll# (ifoldMap (\i -> all# (f i))) {-# INLINE iall #-} -- |@@ -207,7 +211,7 @@ -- -- @'traverse_' l = 'itraverse' '.' 'const'@ itraverse_ :: (FoldableWithIndex i t, Applicative f) => (i -> a -> f b) -> t a -> f ()-itraverse_ f = getTraversed . ifoldMap (\i -> Traversed . void . f i)+itraverse_ f = getTraversed# (ifoldMap (\i -> traversed# (void . f i))) {-# INLINE itraverse_ #-} -- |@@ -230,7 +234,7 @@ -- -- @'mapM_' ≡ 'imapM' '.' 'const'@ imapM_ :: (FoldableWithIndex i t, Monad m) => (i -> a -> m b) -> t a -> m ()-imapM_ f = getSequenced . ifoldMap (\i -> Sequenced . liftM skip . f i)+imapM_ f = getSequenced# (ifoldMap (\i -> sequenced# (liftM skip . f i))) {-# INLINE imapM_ #-} -- |@@ -312,7 +316,7 @@ -- | Fold a container with indices returning only the indices. indices :: FoldableWithIndex i f => Fold (f a) i-indices f = coerce . getFolding . ifoldMap (const . Folding . f)+indices f = coerce . getFolding# (ifoldMap (const . folding# f)) {-# INLINE indices #-} -------------------------------------------------------------------------------@@ -360,7 +364,7 @@ -- -- @'mapM' ≡ 'imapM' '.' 'const'@ imapM :: (TraversableWithIndex i t, Monad m) => (i -> a -> m b) -> t a -> m (t b)-imapM f = unwrapMonad . itraverse (\i -> WrapMonad . f i)+imapM f = unwrapMonad# (itraverse (\i -> wrapMonad# (f i))) {-# INLINE imapM #-} -- | Map each element of a structure to a monadic action,@@ -420,6 +424,17 @@ ifoldMap = ifoldMapOf itraversed instance TraversableWithIndex Int Seq where itraverse = withIndex (indexed traverse)++instance FunctorWithIndex Int Vector where+ imap = V.imap+instance FoldableWithIndex Int Vector where+ ifoldMap = ifoldMapOf itraversed+ ifoldr = V.ifoldr+ ifoldl = V.ifoldl . flip+ ifoldr' = V.ifoldr'+ ifoldl' = V.ifoldl' . flip+instance TraversableWithIndex Int Vector where+ itraverse f = sequenceA . V.imap f instance FunctorWithIndex Int IntMap where imap = imapOf itraversed
src/Control/Lens/Zipper.hs view
@@ -103,7 +103,7 @@ -- used in website navigation. Each breadcrumb in the trail represents a level you -- can move up to. ----- This type operator associates to the right, so you can use a type like+-- This type operator associates to the left, so you can use a type like -- -- @'Top' ':>' ('String','Double') ':>' 'String' ':>' 'Char'@ --@@ -285,7 +285,7 @@ -- -- You can reason about this function as if the definition was: ----- @'fromWithin' l ≡ 'fromJust ' '.' 'within' l@+-- @'fromWithin' l ≡ 'fromJust' '.' 'within' l@ -- -- but it is lazier in such a way that if this invariant is violated, some code -- can still succeed if it is lazy enough in the use of the focused value.
src/Control/Lens/Zoom.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} {-# LANGUAGE CPP #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE LiberalTypeSynonyms #-}@@ -26,6 +27,7 @@ ) where import Control.Lens.Internal+import Control.Lens.Unsafe import Control.Lens.Type import Control.Lens.Getter import Control.Monad@@ -71,11 +73,11 @@ zoom :: Monad m => SimpleLensLike (k c) t s -> m c -> n c instance Monad z => Zoom (Strict.StateT s z) (Strict.StateT t z) (Focusing z) s t where- zoom l (Strict.StateT m) = Strict.StateT $ unfocusing . l (Focusing . m)+ zoom l (Strict.StateT m) = Strict.StateT $ unfocusing# (l (focusing# m)) {-# INLINE zoom #-} instance Monad z => Zoom (Lazy.StateT s z) (Lazy.StateT t z) (Focusing z) s t where- zoom l (Lazy.StateT m) = Lazy.StateT $ unfocusing . l (Focusing . m)+ zoom l (Lazy.StateT m) = Lazy.StateT $ unfocusing# (l (focusing# m)) {-# INLINE zoom #-} instance Zoom m n k s t => Zoom (ReaderT e m) (ReaderT e n) k s t where@@ -87,31 +89,31 @@ {-# INLINE zoom #-} instance (Monoid w, Monad z) => Zoom (Strict.RWST r w s z) (Strict.RWST r w t z) (FocusingWith w z) s t where- zoom l (Strict.RWST m) = Strict.RWST $ \r -> unfocusingWith . l (FocusingWith . m r)+ zoom l (Strict.RWST m) = Strict.RWST $ \r -> unfocusingWith# (l (focusingWith# (m r))) {-# INLINE zoom #-} instance (Monoid w, Monad z) => Zoom (Lazy.RWST r w s z) (Lazy.RWST r w t z) (FocusingWith w z) s t where- zoom l (Lazy.RWST m) = Lazy.RWST $ \r -> unfocusingWith . l (FocusingWith . m r)+ zoom l (Lazy.RWST m) = Lazy.RWST $ \r -> unfocusingWith# (l (focusingWith# (m r))) {-# INLINE zoom #-} instance (Monoid w, Zoom m n k s t) => Zoom (Strict.WriterT w m) (Strict.WriterT w n) (FocusingPlus w k) s t where- zoom l = Strict.WriterT . zoom (\cfd -> unfocusingPlus . l (FocusingPlus . cfd)) . Strict.runWriterT+ zoom l = Strict.WriterT . zoom (\afb -> unfocusingPlus# (l (focusingPlus# afb))) . Strict.runWriterT {-# INLINE zoom #-} instance (Monoid w, Zoom m n k s t) => Zoom (Lazy.WriterT w m) (Lazy.WriterT w n) (FocusingPlus w k) s t where- zoom l = Lazy.WriterT . zoom (\cfd -> unfocusingPlus . l (FocusingPlus . cfd)) . Lazy.runWriterT+ zoom l = Lazy.WriterT . zoom (\afb -> unfocusingPlus# (l (focusingPlus# afb))) . Lazy.runWriterT {-# INLINE zoom #-} instance Zoom m n k s t => Zoom (ListT m) (ListT n) (FocusingOn [] k) s t where- zoom l = ListT . zoom (\cfd -> unfocusingOn . l (FocusingOn . cfd)) . runListT+ zoom l = ListT . zoom (\afb -> unfocusingOn . l (FocusingOn . afb)) . runListT {-# INLINE zoom #-} instance Zoom m n k s t => Zoom (MaybeT m) (MaybeT n) (FocusingMay k) s t where- zoom l = MaybeT . liftM getMay . zoom (\cfd -> unfocusingMay . l (FocusingMay . cfd)) . liftM May . runMaybeT+ zoom l = MaybeT . liftM getMay . zoom (\afb -> unfocusingMay# (l (focusingMay# afb))) . liftM May . runMaybeT {-# INLINE zoom #-} instance (Error e, Zoom m n k s t) => Zoom (ErrorT e m) (ErrorT e n) (FocusingErr e k) s t where- zoom l = ErrorT . liftM getErr . zoom (\cfd -> unfocusingErr . l (FocusingErr . cfd)) . liftM Err . runErrorT+ zoom l = ErrorT . liftM getErr . zoom (\afb -> unfocusingErr# (l (focusingErr# afb))) . liftM Err . runErrorT {-# INLINE zoom #-} -- TODO: instance Zoom m m k a a => Zoom (ContT r m) (ContT r m) k a a where@@ -140,7 +142,7 @@ magnify :: ((b -> k c b) -> a -> k c a) -> m c -> n c instance Monad m => Magnify (ReaderT b m) (ReaderT a m) (Effect m) b a where- magnify l (ReaderT m) = ReaderT $ getEffect . l (Effect . m)+ magnify l (ReaderT m) = ReaderT $ getEffect# (l (effect# m)) {-# INLINE magnify #-} -- | @'magnify' = 'views'@@@ -149,11 +151,11 @@ {-# INLINE magnify #-} instance (Monad m, Monoid w) => Magnify (Strict.RWST b w s m) (Strict.RWST a w s m) (EffectRWS w s m) b a where- magnify l (Strict.RWST m) = Strict.RWST $ getEffectRWS . l (EffectRWS . m)+ magnify l (Strict.RWST m) = Strict.RWST $ getEffectRWS# (l (effectRWS# m)) {-# INLINE magnify #-} instance (Monad m, Monoid w) => Magnify (Lazy.RWST b w s m) (Lazy.RWST a w s m) (EffectRWS w s m) b a where- magnify l (Lazy.RWST m) = Lazy.RWST $ getEffectRWS . l (EffectRWS . m)+ magnify l (Lazy.RWST m) = Lazy.RWST $ getEffectRWS# (l (effectRWS# m)) {-# INLINE magnify #-} instance Magnify m n k b a => Magnify (IdentityT m) (IdentityT n) k b a where
src/Data/ByteString/Lazy/Lens.hs view
@@ -18,7 +18,6 @@ import Control.Lens import Data.ByteString.Lazy as Words import Data.ByteString.Lazy.Char8 as Char8-import Data.List.Lens import Data.Word (Word8) -- | 'Data.ByteString.Lazy.pack' (or 'Data.ByteString.Lazy.unpack') a list of bytes into a 'ByteString'@@ -32,11 +31,11 @@ -- | Traverse the individual bytes in a 'ByteString' ----- @'bytes' = 'from' 'packedBytes' . 'traverseList'@+-- @'bytes' = 'from' 'packedBytes' . 'itraversed'@ -- -- @'anyOf' 'bytes' ('==' 0x80) :: 'ByteString' -> 'Bool'@ bytes :: SimpleIndexedTraversal Int ByteString Word8-bytes = from packedBytes .> traverseList+bytes = from packedBytes .> itraversed {-# INLINE bytes #-} -- | 'Data.ByteString.Lazy.Char8.pack' (or 'Data.ByteString.Lazy.Char8.unpack') a list of characters into a 'ByteString'@@ -56,9 +55,9 @@ -- When writing back to the 'ByteString' it is assumed that every 'Char' -- lies between '\x00' and '\xff'. ----- @'chars' = 'from' 'packedChars' '.>' 'traverseList'@+-- @'chars' = 'from' 'packedChars' '.>' 'itraversed'@ -- -- @'anyOf' 'chars' ('==' \'c\') :: 'ByteString' -> 'Bool'@ chars :: SimpleIndexedTraversal Int ByteString Char-chars = from packedChars .> traverseList+chars = from packedChars .> itraversed {-# INLINE chars #-}
src/Data/ByteString/Strict/Lens.hs view
@@ -17,7 +17,6 @@ import Control.Lens import Data.ByteString as Words import Data.ByteString.Char8 as Char8-import Data.List.Lens import Data.Word (Word8) -- | 'Data.ByteString.pack' (or 'Data.ByteString.unpack') a list of bytes into a 'ByteString'@@ -31,11 +30,11 @@ -- | Traverse each 'Word8' in a 'ByteString' ----- @'bytes' = 'from' 'packedBytes' '.>' 'traverseList'@+-- @'bytes' = 'from' 'packedBytes' '.>' 'itraversed'@ -- -- @'anyOf' 'bytes' ('==' 0x80) :: 'ByteString' -> 'Bool'@ bytes :: SimpleIndexedTraversal Int ByteString Word8-bytes = from packedBytes .> traverseList+bytes = from packedBytes .> itraversed {-# INLINE bytes #-} -- | 'Data.ByteString.Char8.pack' (or 'Data.ByteString.Char8.unpack') a list of characters into a 'ByteString'@@ -59,5 +58,5 @@ -- -- @'anyOf' 'chars' ('==' \'c\') :: 'ByteString' -> 'Bool'@ chars :: SimpleIndexedTraversal Int ByteString Char-chars = from packedChars .> traverseList+chars = from packedChars .> itraversed {-# INLINE chars #-}
src/Data/Data/Lens.hs view
@@ -35,7 +35,8 @@ import Control.Applicative import Control.Arrow ((&&&)) import Control.Exception as E-import Control.Lens+import Control.Lens.Traversal+import Control.Lens.Type import Data.Data import Data.Foldable import qualified Data.HashMap.Strict as M
src/Data/HashSet/Lens.hs view
@@ -15,7 +15,6 @@ ) where import Control.Lens.Getter-import Control.Lens.Internal import Control.Lens.Setter import Data.HashSet as HashSet import Data.Hashable@@ -48,5 +47,5 @@ -- 'setOf' :: ('Eq' a, 'Hashable' a) => 'Control.Lens.Type.Simple' 'Control.Lens.Traversal.Traversal' s a -> s -> 'HashSet' a -- @ setOf :: Hashable a => Getting (HashSet a) s t a b -> s -> HashSet a-setOf l = runAccessor . l (Accessor . HashSet.singleton)+setOf l = views l HashSet.singleton {-# INLINE setOf #-}
src/Data/IntSet/Lens.hs view
@@ -16,7 +16,6 @@ ) where import Control.Lens-import Control.Lens.Internal import Data.IntSet as IntSet -- $setup@@ -56,5 +55,5 @@ -- 'setOf' :: 'Simple' 'Traversal' s 'Int' -> s -> 'IntSet' -- @ setOf :: Getting IntSet s t Int b -> s -> IntSet-setOf l = runAccessor . l (Accessor . IntSet.singleton)+setOf l = views l IntSet.singleton {-# INLINE setOf #-}
src/Data/List/Lens.hs view
@@ -15,36 +15,25 @@ -- ---------------------------------------------------------------------------- module Data.List.Lens- ( _head+ (+ -- * Partial Lenses+ _head , _tail , _last , _init- , interspersed- , intercalated -- * Traversals- , traverseList , traverseHead , traverseTail , traverseInit , traverseLast- , (~:), (=:)- , (<~:), (<=:)- , (++~), (<++~)- , (++=), (<++=) ) where import Control.Applicative import Control.Lens-import Control.Monad.State as State (MonadState, modify)-import Data.List -infixr 4 ++~, <++~-infixl 4 ~:, <~:-infix 4 =:, <=:, ++=, <++=---- | A lens reading and writing to the head of a /non-empty/ list.+-- | A partial 'Lens' reading and writing to the 'head' of a /non-empty/ list. ----- Attempting to read or write to the head of an /empty/ list will result in an 'error'.+-- Attempting to read or write to the 'head' of an /empty/ list will result in an 'error'. -- -- >>> [1,2,3]^._head -- 1@@ -53,9 +42,9 @@ _head f (a:as) = (:as) <$> f a {-# INLINE _head #-} --- | A lens reading and writing to the tail of a /non-empty/ list+-- | A partial 'Lens' reading and writing to the 'tail' of a /non-empty/ list ----- Attempting to read or write to the tail of an /empty/ list will result in an 'error'.+-- Attempting to read or write to the 'tail' of an /empty/ list will result in an 'error'. -- -- >>> _tail .~ [3,4,5] $ [1,2] -- [1,3,4,5]@@ -64,7 +53,7 @@ _tail f (a:as) = (a:) <$> f as {-# INLINE _tail #-} --- | A lens reading and writing to the last element of a /non-empty/ list+-- | A partial 'Lens' reading and writing to the last element of a /non-empty/ list -- -- Attempting to read or write to the last element of an /empty/ list will result in an 'error'. --@@ -76,7 +65,7 @@ _last f (a:as) = (a:) <$> _last f as {-# INLINE _last #-} --- | A lens reading and replacing all but the a last element of a /non-empty/ list+-- | A partial 'Lens' reading and replacing all but the a last element of a /non-empty/ list -- -- Attempting to read or write to all but the last element of an /empty/ list will result in an 'error'. --@@ -87,28 +76,6 @@ _init f as = (++ [Prelude.last as]) <$> f (Prelude.init as) {-# INLINE _init #-} --- | Obtain a version of the list with the supplied value interspersed.------ >>> "abcde"^.interspersed ','--- "a,b,c,d,e"------ > xs^.interspersed a = intersperse a xs-interspersed :: a -> Getter [a] [a]-interspersed = to . intersperse-{-# INLINE interspersed #-}---- | Obtain a version of the list with the supplied value intercalated.-intercalated :: [a] -> Getter [[a]] [a]-intercalated = to . intercalate-{-# INLINE intercalated #-}---- | Indexed traversal of a list. The position in the list is available as the index.-traverseList :: IndexedTraversal Int [a] [b] a b-traverseList = index $ go (0::Int) where- go !n f (x:xs) = (:) <$> f n x <*> go (n + 1) f xs- go _ _ [] = pure []-{-# INLINE traverseList #-}- -- | A traversal for reading and writing to the head of a list -- -- The position of the head in the original list (0) is available as the index.@@ -134,7 +101,7 @@ traverseTail :: SimpleIndexedTraversal Int [a] a traverseTail = index $ \f aas -> case aas of [] -> pure []- (a:as) -> (a:) <$> withIndex traverseList (f . (+1)) as+ (a:as) -> (a:) <$> itraverse (f . (+1)) as {-# INLINE traverseTail #-} -- | A traversal the last element in a list@@ -164,119 +131,5 @@ traverseInit :: SimpleIndexedTraversal Int [a] a traverseInit = index $ \f aas -> case aas of [] -> pure []- as -> (++ [Prelude.last as]) <$> withIndex traverseList f (Prelude.init as)+ as -> (++ [Prelude.last as]) <$> itraverse f (Prelude.init as) {-# INLINE traverseInit #-}---- | Cons onto the list(s) referenced by a 'Setter'.------ >>> 'h' ~: _1 $ ("ello","world")--- ("hello","world")------ @--- ('~:') :: b -> 'Simple' 'Setter' s [a] -> s -> s--- ('~:') :: b -> 'Simple' 'Traversal' s [a] -> s -> s--- ('~:') :: b -> 'Simple' 'Lens' s [a] -> s -> s--- ('~:') :: b -> 'Simple' 'Iso' s [a] -> s -> s--- @-(~:) :: a -> Setting s t [a] [a] -> s -> t-n ~: l = over l (n :)-{-# INLINE (~:) #-}---- | Cons onto the list(s) referenced by a 'Setter' in your monad state------ @--- ('=:') :: 'MonadState' s m => a -> 'Simple' 'Setter' s [a] -> m ()--- ('=:') :: 'MonadState' s m => a -> 'Simple' 'Traversal' s [a] -> m ()--- ('=:') :: 'MonadState' s m => a -> 'Simple' 'Lens' s [a] -> m ()--- ('=:') :: 'MonadState' s m => a -> 'Simple' 'Iso' s [a] -> m ()--- @-(=:) :: MonadState s m => a -> SimpleSetting s [a] -> m ()-n =: l = modify (n ~: l)-{-# INLINE (=:) #-}---- | Cons onto the list(s) referenced by a 'Lens' (or 'Traversal'), returning the result.------ If you use this with a 'Traversal' you will receive back the concatenation of all of--- the resulting lists instead of an individual result.------ >>> 'h' <~: _1 $ ("ello","world")--- ("hello",("hello","world"))------ @--- ('<~:') :: b -> 'Simple' 'Lens' s [a] -> s -> ([a], s)--- ('<~:') :: b -> 'Simple' 'Iso' s [a] -> s -> ([a], s)--- ('<~:') :: b -> 'Simple' 'Traversal' s [a] -> s -> ([a], s)--- @-(<~:) :: a -> LensLike ((,)[a]) s t [a] [a] -> s -> ([a], t)-n <~: l = l <%~ (n :)-{-# INLINE (<~:) #-}---- | Cons onto the list(s) referenced by a 'Lens' (or 'Traversal') into your monad state,--- returning the result.------ If you use this with a 'Traversal', you will receive back the concatenation of all--- of the resulting lists instead of an individual result.------ @--- ('<=:') :: 'MonadState' s m => 'Simple' 'Lens' s [a] -> a -> m [a]--- ('<=:') :: 'MonadState' s m => 'Simple' 'Iso' s [a] -> a -> m [a]--- ('<=:') :: 'MonadState' s m => 'Simple' 'Traversal' s [a] -> a -> m [a]--- @-(<=:) :: MonadState s m => a -> SimpleLensLike ((,)[a]) s [a] -> m [a]-n <=: l = l <%= (n :)-{-# INLINE (<=:) #-}----- | Append to the target of a list-valued setter by appending to it with ('++').------ ('Data.Monoid.<>~') generalizes this operation to an arbitrary 'Monoid'.------ >>> :m + Control.Lens--- >>> both ++~ "!!!" $ ("hello","world")--- ("hello!!!","world!!!")------ @--- ('++~') :: 'Simple' 'Setter' s [a] -> [a] -> s -> s--- ('++~') :: 'Simple' 'Iso' s [a] -> [a] -> s -> s--- ('++~') :: 'Simple' 'Lens' s [a] -> [a] -> s -> s--- ('++~') :: 'Simple' 'Traversal' s [a] -> [a] -> s -> s--- @-(++~) :: Setting s t [a] [a] -> [a] -> s -> t-l ++~ n = over l (++ n)-{-# INLINE (++~) #-}---- | Append to the target(s) of a 'Simple' 'Lens', 'Iso', 'Setter' or 'Traversal' with ('++') in the current state.------ ('Data.Monoid.<>=') generalizes this operation to an arbitrary 'Monoid'.------ @--- ('++=') :: 'MonadState' s m => 'Simple' 'Setter' s [a] -> [a] -> m ()--- ('++=') :: 'MonadState' s m => 'Simple' 'Iso' s [a] -> [a] -> m ()--- ('++=') :: 'MonadState' s m => 'Simple' 'Lens' s [a] -> [a] -> m ()--- ('++=') :: 'MonadState' s m => 'Simple' 'Traversal' s [a] -> [a] -> m ()--- @-(++=) :: MonadState s m => SimpleSetting s [a] -> [a] -> m ()-l ++= b = State.modify (l ++~ b)-{-# INLINE (++=) #-}---- | Append onto the end of the list targeted by a 'Lens' and return the result.------ ('Data.Monoid.<<>~') generalizes this operation to an arbitrary 'Monoid'.------ When using a 'Traversal', the result returned is actually the concatenation of all of the results.------ When you do not need the result of the operation, ('++~') is more flexible.-(<++~) :: LensLike ((,)[a]) s t [a] [a] -> [a] -> s -> ([a], t)-l <++~ m = l <%~ (++ m)-{-# INLINE (<++~) #-}---- | Append onto the end of the list targeted by a 'Lens' into the current monadic state, and return the result.------ ('Data.Monoid.<<>=') generalizes this operation to an arbitrary 'Monoid'.------ When using a 'Traversal', the result returned is actually the concatenation of all of the results.------ When you do not need the result of the operation, ('++=') is more flexible.-(<++=) :: MonadState s m => SimpleLensLike ((,)[a]) s [a] -> [a] -> m [a]-l <++= m = l <%= (++ m)-{-# INLINE (<++=) #-}
+ src/Data/List/Split/Lens.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LiberalTypeSynonyms #-}+----------------------------------------------------------------------------+-- |+-- Module : Data.List.Split.Lens+-- Copyright : (C) 2012 Edward Kmett, Alexander Altman+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : Rank2Types+--+-- Lenses for working with Data.List.Split+--+----------------------------------------------------------------------------+module Data.List.Split.Lens+ (+ -- * Splitting Folds+ splitting+ , splittingOn+ , splittingOneOf+ , splittingWhen+ , endingBy+ , endingByOneOf+ , wordingBy+ , liningBy+ , chunking+ , splittingPlaces+ , splittingPlacesBlanks+ -- * Lenses for 'Splitter' Internals+ , delimiters+ , delimiting+ , condensing+ , keepInitialBlanks+ , keepFinalBlanks+ ) where++import Control.Applicative+import Control.Lens+import Control.Lens.Internal+import Data.List.Split+import Data.List.Split.Internals++-- $setup+-- >>> import Control.Lens++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' according to the given splitting strategy.+--+-- @+-- 'splitting' :: 'Splitter' a -> 'Fold' i s a -> 'Fold' [i] s [a]+-- @+splitting :: (Applicative f, Gettable f) => Splitter a -> Getting [a] s s a a -> LensLike f s s [a] [a]+splitting s l f = coerce . traverse f . split s . toListOf l+{-# INLINE splitting #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' on the given delimiter.+--+-- Equivalent to @'splitting' '.' 'dropDelims' '.' 'onSublist'@.+--+-- @+-- 'splittingOn' :: 'Eq' a => [a] -> 'Fold' s a -> 'Fold' s [a]+-- @+splittingOn :: (Applicative f, Gettable f, Eq a) => [a] -> Getting [a] s s a a -> LensLike f s s [a] [a]+splittingOn s l f = coerce . traverse f . splitOn s . toListOf l+{-# INLINE splittingOn #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' on any of the given elements.+--+-- Equivalent to @'splitting' '.' 'dropDelims' '.' 'oneOf'@.+--+-- @+-- 'splittingOn' :: 'Eq' a => [a] -> 'Fold' s a -> 'Fold' s [a]+-- @+splittingOneOf :: (Applicative f, Gettable f, Eq a) => [a] -> Getting [a] s s a a -> LensLike f s s [a] [a]+splittingOneOf s l f = coerce . traverse f . splitOneOf s . toListOf l+{-# INLINE splittingOneOf #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' on elements satisfying the given predicate.+--+-- Equivalent to @'splitting' '.' 'dropDelims' '.' 'whenElt'@.+--+-- @+-- 'splittingOn' :: (a -> 'Bool') -> 'Fold' s a -> 'Fold' s [a]+-- @+splittingWhen :: (Applicative f, Gettable f, Eq a) => (a -> Bool) -> Getting [a] s s a a -> LensLike f s s [a] [a]+splittingWhen s l f = coerce . traverse f . splitWhen s . toListOf l+{-# INLINE splittingWhen #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into chunks terminated by the given delimiter.+--+-- Equivalent to @'splitting' '.' 'dropDelims' '.' 'onSublist'@.+--+-- @+-- 'endingBy' :: 'Eq' a => [a] -> 'Fold' s a -> 'Fold' s [a]+-- @+endingBy :: (Applicative f, Gettable f, Eq a) => [a] -> Getting [a] s s a a -> LensLike f s s [a] [a]+endingBy s l f = coerce . traverse f . endBy s . toListOf l+{-# INLINE endingBy #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into chunks terminated by any of the given elements.+--+-- Equivalent to @'splitting' '.' 'dropFinalBlank' '.' 'dropDelims' '.' 'oneOf'@.+--+-- @+-- 'endingByOneOf' :: 'Eq' a => [a] -> 'Fold' s a -> 'Fold' s [a]+-- @+endingByOneOf :: (Applicative f, Gettable f, Eq a) => [a] -> Getting [a] s s a a -> LensLike f s s [a] [a]+endingByOneOf s l f = coerce . traverse f . endByOneOf s . toListOf l+{-# INLINE endingByOneOf #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into "words", with word boundaries indicated by the given predicate.+--+-- Equivalent to @'splitting' '.' 'dropBlanks' '.' 'dropDelims' '.' 'whenElt'@.+--+-- @+-- 'wordingBy' :: (a -> 'Bool') -> 'Fold' a -> 'Fold' s [a]+-- @+wordingBy :: (Applicative f, Gettable f, Eq a) => (a -> Bool) -> Getting [a] s s a a -> LensLike f s s [a] [a]+wordingBy s l f = coerce . traverse f . wordsBy s . toListOf l+{-# INLINE wordingBy #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into "lines", with line boundaries indicated by the given predicate.+--+-- Equivalent to @'splitting' '.' 'dropFinalBlank' '.' 'dropDelims' '.' 'whenElt'@.+--+-- @+-- 'liningBy' :: (a -> 'Bool') -> 'Fold' s a -> 'Fold' s [a]+-- @+liningBy :: (Applicative f, Gettable f, Eq a) => (a -> Bool) -> Getting [a] s s a a -> LensLike f s s [a] [a]+liningBy s l f = coerce . traverse f . linesBy s . toListOf l+{-# INLINE liningBy #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into length-@n@ pieces.+--+-- @+-- 'chunkingOf' :: 'Int' -> 'Fold' s a -> 'Fold' s [a]+-- @+chunking :: (Applicative f, Gettable f) => Int -- ^ @n@+ -> Getting [a] s s a a -> LensLike f s s [a] [a]+chunking s l f = coerce . traverse f . chunksOf s . toListOf l+{-# INLINE chunking #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into chunks of the given lengths, .+--+-- @+-- 'splittingPlaces' :: 'Integral' n => [n] -> 'Fold' s a -> 'Fold' s [a]+-- @+splittingPlaces :: (Applicative f, Gettable f, Integral n) => [n] -> Getting [a] s s a a -> LensLike f s s [a] [a]+splittingPlaces s l f = coerce . traverse f . splitPlaces s . toListOf l+{-# INLINE splittingPlaces #-}++-- | Obtain a 'Fold' by splitting another 'Fold', 'Control.Lens.Type.Lens', 'Getter' or 'Control.Lens.Traversal.Traversal' into chunks of the given lengths. Unlike 'splittingPlaces', the output 'Fold' will always be the same length as the first input argument.+--+-- @+-- 'splittingPlacesBlanks' :: 'Integral' n => [n] -> 'Fold' s a -> 'Fold' s [a]+-- @+splittingPlacesBlanks :: (Applicative f, Gettable f, Integral n) => [n] -> Getting [a] s s a a -> LensLike f s s [a] [a]+splittingPlacesBlanks s l f = coerce . traverse f . splitPlacesBlanks s . toListOf l+{-# INLINE splittingPlacesBlanks #-}+++-- | Modify or retrieve the list of delimiters for a 'Splitter'.+delimiters :: Lens (Splitter a) (Splitter b) [a -> Bool] [b -> Bool]+delimiters f s@Splitter { delimiter = Delimiter ds } = (\ds' -> s { delimiter = Delimiter ds' }) <$> f ds++-- | Modify or retrieve the policy for what a 'Splitter' to do with delimiters.+delimiting :: Simple Lens (Splitter a) DelimPolicy+delimiting f s@Splitter { delimPolicy = p } = (\p' -> s { delimPolicy = p' }) <$> f p++-- | Modify or retrieve the policy for what a 'Splitter' should about consecutive delimiters.+condensing :: Simple Lens (Splitter a) Bool+condensing f s@Splitter { condensePolicy = p } = (\p' -> s { condensePolicy = i p' }) <$> f (o p) where+ i True = Condense+ i False = KeepBlankFields+ o Condense = True+ o KeepBlankFields = False++-- | Modify or retrieve the policy for whether a 'Splitter' should drop an initial blank.+keepInitialBlanks :: Simple Lens (Splitter a) Bool+keepInitialBlanks f s@Splitter { initBlankPolicy = p } = (\p' -> s { initBlankPolicy = end p' }) <$> f (keeps p)++-- | Modify or retrieve the policy for whether a 'Splitter' should drop a final blank.+keepFinalBlanks :: Simple Lens (Splitter a) Bool+keepFinalBlanks f s@Splitter { finalBlankPolicy = p } = (\p' -> s { finalBlankPolicy = end p' }) <$> f (keeps p)++-- utilities++end :: Bool -> EndPolicy+end True = KeepBlank+end False = DropBlank++keeps :: EndPolicy -> Bool+keeps KeepBlank = True+keeps DropBlank = False
src/Data/Set/Lens.hs view
@@ -15,7 +15,6 @@ ) where import Control.Lens.Getter-import Control.Lens.Internal import Control.Lens.Setter import Data.Set as Set @@ -47,5 +46,5 @@ -- 'setOf' :: 'Ord' a => 'Control.Lens.Type.Simple' 'Control.Lens.Traversal.Traversal' s a -> s -> 'Set' a -- @ setOf :: Getting (Set a) s t a b -> s -> Set a-setOf l = runAccessor . l (Accessor . Set.singleton)+setOf l = views l Set.singleton {-# INLINE setOf #-}
src/Data/Tree/Lens.hs view
@@ -17,7 +17,6 @@ import Control.Lens import Data.Functor-import Data.List.Lens import Data.Tree -- | A 'Lens' that focuses on the root of a 'Tree'.@@ -33,5 +32,5 @@ -- -- @'toListOf' 'branches' ≡ 'subForest'@ branches :: SimpleIndexedTraversal Int (Tree a) (Tree a)-branches = index $ \ f (Node a as) -> Node a <$> withIndex traverseList f as+branches = index $ \ f (Node a as) -> Node a <$> itraverse f as {-# INLINE branches #-}
+ src/Data/Vector/Generic/Lens.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LiberalTypeSynonyms #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-------------------------------------------------------------------------------+-- |+-- Module : Data.Vector.Generic.Lens+-- Copyright : (C) 2012 Edward Kmett+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : non-portable+--+-- This module provides lenses and traversals for working with generic vectors.+-------------------------------------------------------------------------------+module Data.Vector.Generic.Lens+ ( toVectorOf+ -- * Isomorphisms+ , forced+ , vector+ , asStream+ , asStreamR+ , cloned+ , reversed+ -- * Lenses+ , _head+ , _tail+ , _last+ , _init+ , sliced+ -- * Traversal of individual indices+ , atIndex+ , atIndices+ ) where++import Control.Applicative+import Control.Lens+import Data.Vector.Generic as V hiding (zip, filter)+import Data.Vector.Fusion.Stream (Stream)+import Data.Vector.Generic.New (New)+import Prelude hiding ((++), length, head, tail, init, last, map, reverse)+import Data.List (nub)++-- $setup+-- >>> import Data.Vector as Vector++-- | A lens reading and writing to the 'head' of a /non-empty/ 'Vector'+--+-- Attempting to read or write to the 'head' of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> Vector.fromList [1,2,3]^._head+-- 1+_head :: Vector v a => SimpleLens (v a) a+_head f v = (\a -> v // [(0,a)]) <$> f (head v)+{-# INLINE _head #-}++-- | A 'Lens' reading and writing to the 'last' element of a /non-empty/ 'Vector'+--+-- Attempting to read or write to the 'last' element of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> Vector.fromList [1,2]^._last+-- 2+_last :: Vector v a => SimpleLens (v a) a+_last f v = (\a -> v // [(length v - 1, a)]) <$> f (last v)+{-# INLINE _last #-}++-- | A lens reading and writing to the 'tail' of a /non-empty/ 'Vector'+--+-- Attempting to read or write to the 'tail' of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> _tail .~ Vector.fromList [3,4,5] $ Vector.fromList [1,2]+-- fromList [1,3,4,5]+_tail :: Vector v a => SimpleLens (v a) (v a)+_tail f v = cons (head v) <$> f (tail v)+{-# INLINE _tail #-}++-- | A 'Lens' reading and replacing all but the a 'last' element of a /non-empty/ 'Vector'+--+-- Attempting to read or write to all but the 'last' element of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> Vector.fromList [1,2,3,4]^._init+-- fromList [1,2,3]+_init :: Vector v a => SimpleLens (v a) (v a)+_init f v = (`snoc` last v) <$> f (init v)+{-# INLINE _init #-}++-- | @sliced i n@ provides a lens that edits the @n@ elements starting at index @i@ from a lens.+--+-- This is only a valid lens if you do not change the length of the resulting 'Vector'.+--+-- Attempting to return a longer or shorter vector will result in violations of the 'Lens' laws.+sliced :: Vector v a => Int -- ^ @i@ starting index+ -> Int -- ^ @n@ length+ -> SimpleLens (v a) (v a)+sliced i n f v = (\ v0 -> v // zip [i..i+n-1] (V.toList v0)) <$> f (slice i n v)+{-# INLINE sliced #-}++-- | Similar to 'toListOf', but returning a 'Vector'.+toVectorOf :: Vector v a => Getting [a] s t a b -> s -> v a+toVectorOf l s = fromList (toListOf l s)+{-# INLINE toVectorOf #-}++-- | Convert a list to a 'Vector' (or back)+vector :: Vector v a => Simple Iso [a] (v a)+vector = iso fromList V.toList+{-# INLINE vector #-}++-- | Convert a 'Vector' to a finite 'Stream' (or back)+asStream :: Vector v a => Simple Iso (v a) (Stream a)+asStream = iso stream unstream+{-# INLINE asStream #-}++-- | Convert a 'Vector' to a finite 'Stream' from right to left (or back)+asStreamR :: Vector v a => Simple Iso (v a) (Stream a)+asStreamR = iso streamR unstreamR+{-# INLINE asStreamR #-}++-- | Convert a 'Vector' back and forth to an initializer that when run produces a copy of the 'Vector'.+cloned :: Vector v a => Simple Iso (v a) (New v a)+cloned = iso clone new+{-# INLINE cloned #-}++-- | Convert a 'Vector' to a version that doesn't retain any extra memory.+forced :: Vector v a => Simple Iso (v a) (v a)+forced = iso force force+{-# INLINE forced #-}++-- | Convert a 'Vector' to a version with all the elements in the reverse order+reversed :: Vector v a => Simple Iso (v a) (v a)+reversed = iso reverse reverse+{-# INLINE reversed #-}++-- | This is a more efficient version of 'element' that works for any 'Vector'.+--+-- @atIndex n@ is only a valid 'Lens' into a 'Vector' with 'length' at least @n + 1@.+atIndex :: Vector v a => Int -> SimpleIndexedLens Int (v a) a+atIndex i = index $ \ f v -> (\ a -> v // [(i, a)]) <$> f i (v ! i)+{-# INLINE atIndex #-}++-- | This 'Traversal' will ignore any duplicates in the supplied list of indices.+--+-- >>> toListOf (atIndices [1,3,2,5,9,10]) $ Vector.fromList [2,4..40]+-- [4,8,6,12,20,22]+atIndices :: Vector v a => [Int] -> SimpleIndexedTraversal Int (v a) a+atIndices is = index $ \ f v -> let+ l = length v+ is' = nub $ filter (<l) is+ in fmap ((v //) . zip is') . traverse (uncurry f) . zip is $ fmap (v !) is'+{-# INLINE atIndices #-}
+ src/Data/Vector/Lens.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LiberalTypeSynonyms #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-------------------------------------------------------------------------------+-- |+-- Module : Data.Vector.Lens+-- Copyright : (C) 2012 Edward Kmett+-- License : BSD-style (see the file LICENSE)+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : non-portable+--+-- This module provides lenses and traversals for working with generic vectors.+-------------------------------------------------------------------------------+module Data.Vector.Lens+ ( toVectorOf+ -- * Isomorphisms+ , vector+ , reversed+ , forced+ -- * Lenses+ , _head+ , _tail+ , _last+ , _init+ , sliced+ -- * Traversal of individual indices+ , atIndex+ , atIndices+ ) where++import Control.Applicative+import Control.Lens+import Data.Vector as Vector hiding (zip, filter)+import Prelude hiding ((++), length, head, tail, init, last, map, reverse)+import Data.List (nub)++-- | A lens reading and writing to the 'head' of a /non-empty/ 'Vector'+--+-- Attempting to read or write to the 'head' of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> Vector.fromList [1,2,3]^._head+-- 1+_head :: SimpleLens (Vector a) a+_head f v = (\a -> v // [(0,a)]) <$> f (head v)+{-# INLINE _head #-}++-- | A 'Lens' reading and writing to the 'last' element of a /non-empty/ 'Vector'+--+-- Attempting to read or write to the 'last' element of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> Vector.fromList [1,2]^._last+-- 2+_last :: SimpleLens (Vector a) a+_last f v = (\a -> v // [(length v - 1, a)]) <$> f (last v)+{-# INLINE _last #-}++-- | A lens reading and writing to the 'tail' of a /non-empty/ 'Vector'+--+-- Attempting to read or write to the 'tail' of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> _tail .~ Vector.fromList [3,4,5] $ Vector.fromList [1,2]+-- fromList [1,3,4,5]+_tail :: SimpleLens (Vector a) (Vector a)+_tail f v = cons (head v) <$> f (tail v)+{-# INLINE _tail #-}++-- | A 'Lens' reading and replacing all but the a 'last' element of a /non-empty/ 'Vector'+--+-- Attempting to read or write to all but the 'last' element of an /empty/ 'Vector' will result in an 'error'.+--+-- >>> Vector.fromList [1,2,3,4]^._init+-- fromList [1,2,3]+_init :: SimpleLens (Vector a) (Vector a)+_init f v = (`snoc` last v) <$> f (init v)+{-# INLINE _init #-}++-- | @sliced i n@ provides a lens that edits the @n@ elements starting at index @i@ from a lens.+--+-- This is only a valid lens if you do not change the length of the resulting 'Vector'.+--+-- Attempting to return a longer or shorter vector will result in violations of the 'Lens' laws.+sliced :: Int -- ^ @i@ starting index+ -> Int -- ^ @n@ length+ -> SimpleLens (Vector a) (Vector a)+sliced i n f v = (\ v0 -> v // zip [i..i+n-1] (toList v0)) <$> f (slice i n v)+{-# INLINE sliced #-}++-- | Similar to 'toListOf', but returning a 'Vector'.+toVectorOf :: Getting [a] s t a b -> s -> Vector a+toVectorOf l s = fromList (toListOf l s)+{-# INLINE toVectorOf #-}++-- | Convert a list to a 'Vector' (or back)+vector :: Iso [a] [b] (Vector a) (Vector b)+vector = isos fromList toList fromList toList+{-# INLINE vector #-}++-- | Convert a 'Vector' to a version with all the elements in the reverse order+reversed :: Iso (Vector a) (Vector b) (Vector a) (Vector b)+reversed = isos reverse reverse reverse reverse+{-# INLINE reversed #-}++-- | Convert a 'Vector' to a version that doesn't retain any extra memory.+forced :: Iso (Vector a) (Vector b) (Vector a) (Vector b)+forced = isos force force force force+{-# INLINE forced #-}++-- | This is a more efficient version of 'element' that works for any 'Vector'.+--+-- @atIndex n@ is only a valid 'Lens' into a 'Vector' with 'length' at least @n + 1@.+atIndex :: Int -> SimpleIndexedLens Int (Vector a) a+atIndex i = index $ \ f v -> (\ a -> v // [(i, a)]) <$> f i (v ! i)+{-# INLINE atIndex #-}++-- | This 'Traversal' will ignore any duplicates in the supplied list of indices.+--+-- >>> toListOf (atIndices [1,3,2,5,9,10]) $ Vector.fromList [2,4..40]+-- [4,8,6,12,20,22]+atIndices :: [Int] -> SimpleIndexedTraversal Int (Vector a) a+atIndices is = index $ \ f v -> let+ l = length v+ is' = nub $ filter (<l) is+ in fmap ((v //) . zip is') . traverse (uncurry f) . zip is $ fmap (v !) is'+{-# INLINE atIndices #-}
tests/hunit.hs view
@@ -5,7 +5,8 @@ import Control.Monad.State import Data.Char import Data.List as List-import Data.List.Lens+import Data.Monoid+import Data.Monoid.Lens import Data.Map as Map import Test.Framework.Providers.HUnit import Test.Framework.TH@@ -188,34 +189,34 @@ { _y = ((trig % _box % _low % _y) + 1) } } } case_append_to_record_field =- (trig % points ++~ [ origin ])- @?= trig { _points = (trig % _points) ++ [ origin ] }+ (trig % points <>~ [ origin ])+ @?= trig { _points = (trig % _points) <> [ origin ] } case_append_to_state_record_field = do runState test trig @?= ((), trig') where- test = points ++= [ origin ]- trig' = trig { _points = (trig % _points) ++ [ origin ] }+ test = points <>= [ origin ]+ trig' = trig { _points = (trig % _points) <> [ origin ] } case_append_to_record_field_and_access_new_value =- (trig % points <++~ [ origin ])- @?= (_points trig ++ [ origin ], trig { _points = (trig % _points) ++ [ origin ] })+ (trig % points <<>~ [ origin ])+ @?= (_points trig <> [ origin ], trig { _points = (trig % _points) <> [ origin ] }) case_append_to_state_record_field_and_access_new_value = do- runState test trig @?= (_points trig ++ [ origin ], trig')+ runState test trig @?= (_points trig <> [ origin ], trig') where- test = points <++= [ origin ]- trig' = trig { _points = (trig % _points) ++ [ origin ] }+ test = points <<>= [ origin ]+ trig' = trig { _points = (trig % _points) <> [ origin ] } case_append_to_record_field_and_access_old_value =- (trig % points <<%~ (++[origin]))- @?= (_points trig, trig { _points = (trig % _points) ++ [ origin ] })+ (trig % points <<%~ (<>[origin]))+ @?= (_points trig, trig { _points = (trig % _points) <> [ origin ] }) case_append_to_state_record_field_and_access_old_value = do runState test trig @?= (_points trig, trig') where- test = points <<%= (++[origin])- trig' = trig { _points = (trig % _points) ++ [ origin ] }+ test = points <<%= (<>[origin])+ trig' = trig { _points = (trig % _points) <> [ origin ] } case_read_maybe_map_entry = trig^.labels.at origin @?= Just "Origin"