{-# LANGUAGE CPP #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} #ifndef MIN_VERSION_base #define MIN_VERSION_base(x,y,z) 1 #endif ------------------------------------------------------------------------------- -- | -- Module : Control.Lens.Tuple -- Copyright : (C) 2012-16 Edward Kmett -- License : BSD-style (see the file LICENSE) -- Maintainer : Edward Kmett -- Stability : provisional -- Portability : Rank2Types -- ------------------------------------------------------------------------------- module Control.Lens.Tuple ( -- * Tuples Field1(..) , Field2(..) , Field3(..) , Field4(..) , Field5(..) , Field6(..) , Field7(..) , Field8(..) , Field9(..) -- * Strict variations , _1', _2', _3', _4', _5', _6', _7', _8', _9' ) where import Control.Lens.Lens import Data.Functor.Identity import Data.Functor.Product import Data.Profunctor (dimap) import Data.Proxy (Proxy (Proxy)) import GHC.Generics (Generic (..), (:*:) (..), K1 (..), M1 (..), U1 (..)) #if !MIN_VERSION_base(4,8,0) import Control.Applicative #endif -- $setup -- >>> :set -XNoOverloadedStrings -- >>> import Control.Lens -- | Provides access to 1st field of a tuple. class Field1 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 1st field of a tuple (and possibly change its type). -- -- >>> (1,2)^._1 -- 1 -- -- >>> _1 .~ "hello" $ (1,2) -- ("hello",2) -- -- >>> (1,2) & _1 .~ "hello" -- ("hello",2) -- -- >>> _1 putStrLn ("hello","world") -- hello -- ((),"world") -- -- This can also be used on larger tuples as well: -- -- >>> (1,2,3,4,5) & _1 +~ 41 -- (42,2,3,4,5) -- -- @ -- '_1' :: 'Lens' (a,b) (a',b) a a' -- '_1' :: 'Lens' (a,b,c) (a',b,c) a a' -- '_1' :: 'Lens' (a,b,c,d) (a',b,c,d) a a' -- ... -- '_1' :: 'Lens' (a,b,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a' -- @ _1 :: Lens s t a b default _1 :: (Generic s, Generic t, GIxed N0 (Rep s) (Rep t) a b) => Lens s t a b _1 = ix proxyN0 {-# INLINE _1 #-} instance Field1 (Identity a) (Identity b) a b where _1 f (Identity a) = Identity <$> f a instance Field1 (Product f g a) (Product f' g a) (f a) (f' a) where _1 f (Pair a b) = flip Pair b <$> f a instance Field1 ((f :*: g) p) ((f' :*: g) p) (f p) (f' p) where _1 f (l :*: r) = (:*: r) <$> f l -- | @ -- '_1' k ~(a,b) = (\\a' -> (a',b)) 'Data.Functor.<$>' k a -- @ instance Field1 (a,b) (a',b) a a' where _1 k ~(a,b) = k a <&> \a' -> (a',b) {-# INLINE _1 #-} instance Field1 (a,b,c) (a',b,c) a a' where _1 k ~(a,b,c) = k a <&> \a' -> (a',b,c) {-# INLINE _1 #-} instance Field1 (a,b,c,d) (a',b,c,d) a a' where _1 k ~(a,b,c,d) = k a <&> \a' -> (a',b,c,d) {-# INLINE _1 #-} instance Field1 (a,b,c,d,e) (a',b,c,d,e) a a' where _1 k ~(a,b,c,d,e) = k a <&> \a' -> (a',b,c,d,e) {-# INLINE _1 #-} instance Field1 (a,b,c,d,e,f) (a',b,c,d,e,f) a a' where _1 k ~(a,b,c,d,e,f) = k a <&> \a' -> (a',b,c,d,e,f) {-# INLINE _1 #-} instance Field1 (a,b,c,d,e,f,g) (a',b,c,d,e,f,g) a a' where _1 k ~(a,b,c,d,e,f,g) = k a <&> \a' -> (a',b,c,d,e,f,g) {-# INLINE _1 #-} instance Field1 (a,b,c,d,e,f,g,h) (a',b,c,d,e,f,g,h) a a' where _1 k ~(a,b,c,d,e,f,g,h) = k a <&> \a' -> (a',b,c,d,e,f,g,h) {-# INLINE _1 #-} instance Field1 (a,b,c,d,e,f,g,h,i) (a',b,c,d,e,f,g,h,i) a a' where _1 k ~(a,b,c,d,e,f,g,h,i) = k a <&> \a' -> (a',b,c,d,e,f,g,h,i) {-# INLINE _1 #-} -- | Provides access to the 2nd field of a tuple. class Field2 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 2nd field of a tuple. -- -- >>> _2 .~ "hello" $ (1,(),3,4) -- (1,"hello",3,4) -- -- >>> (1,2,3,4) & _2 *~ 3 -- (1,6,3,4) -- -- >>> _2 print (1,2) -- 2 -- (1,()) -- -- @ -- 'Control.Lens.Fold.anyOf' '_2' :: (s -> 'Bool') -> (a, s) -> 'Bool' -- 'Data.Traversable.traverse' '.' '_2' :: ('Control.Applicative.Applicative' f, 'Data.Traversable.Traversable' t) => (a -> f b) -> t (s, a) -> f (t (s, b)) -- 'Control.Lens.Fold.foldMapOf' ('Data.Traversable.traverse' '.' '_2') :: ('Data.Traversable.Traversable' t, 'Data.Monoid.Monoid' m) => (s -> m) -> t (b, s) -> m -- @ _2 :: Lens s t a b default _2 :: (Generic s, Generic t, GIxed N1 (Rep s) (Rep t) a b) => Lens s t a b _2 = ix proxyN1 {-# INLINE _2 #-} instance Field2 (Product f g a) (Product f g' a) (g a) (g' a) where _2 f (Pair a b) = Pair a <$> f b instance Field2 ((f :*: g) p) ((f :*: g') p) (g p) (g' p) where _2 f (l :*: r) = (l :*:) <$> f r -- | @ -- '_2' k ~(a,b) = (\\b' -> (a,b')) 'Data.Functor.<$>' k b -- @ instance Field2 (a,b) (a,b') b b' where _2 k ~(a,b) = k b <&> \b' -> (a,b') {-# INLINE _2 #-} instance Field2 (a,b,c) (a,b',c) b b' where _2 k ~(a,b,c) = k b <&> \b' -> (a,b',c) {-# INLINE _2 #-} instance Field2 (a,b,c,d) (a,b',c,d) b b' where _2 k ~(a,b,c,d) = k b <&> \b' -> (a,b',c,d) {-# INLINE _2 #-} instance Field2 (a,b,c,d,e) (a,b',c,d,e) b b' where _2 k ~(a,b,c,d,e) = k b <&> \b' -> (a,b',c,d,e) {-# INLINE _2 #-} instance Field2 (a,b,c,d,e,f) (a,b',c,d,e,f) b b' where _2 k ~(a,b,c,d,e,f) = k b <&> \b' -> (a,b',c,d,e,f) {-# INLINE _2 #-} instance Field2 (a,b,c,d,e,f,g) (a,b',c,d,e,f,g) b b' where _2 k ~(a,b,c,d,e,f,g) = k b <&> \b' -> (a,b',c,d,e,f,g) {-# INLINE _2 #-} instance Field2 (a,b,c,d,e,f,g,h) (a,b',c,d,e,f,g,h) b b' where _2 k ~(a,b,c,d,e,f,g,h) = k b <&> \b' -> (a,b',c,d,e,f,g,h) {-# INLINE _2 #-} instance Field2 (a,b,c,d,e,f,g,h,i) (a,b',c,d,e,f,g,h,i) b b' where _2 k ~(a,b,c,d,e,f,g,h,i) = k b <&> \b' -> (a,b',c,d,e,f,g,h,i) {-# INLINE _2 #-} -- | Provides access to the 3rd field of a tuple. class Field3 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 3rd field of a tuple. _3 :: Lens s t a b default _3 :: (Generic s, Generic t, GIxed N2 (Rep s) (Rep t) a b) => Lens s t a b _3 = ix proxyN2 {-# INLINE _3 #-} instance Field3 (a,b,c) (a,b,c') c c' where _3 k ~(a,b,c) = k c <&> \c' -> (a,b,c') {-# INLINE _3 #-} instance Field3 (a,b,c,d) (a,b,c',d) c c' where _3 k ~(a,b,c,d) = k c <&> \c' -> (a,b,c',d) {-# INLINE _3 #-} instance Field3 (a,b,c,d,e) (a,b,c',d,e) c c' where _3 k ~(a,b,c,d,e) = k c <&> \c' -> (a,b,c',d,e) {-# INLINE _3 #-} instance Field3 (a,b,c,d,e,f) (a,b,c',d,e,f) c c' where _3 k ~(a,b,c,d,e,f) = k c <&> \c' -> (a,b,c',d,e,f) {-# INLINE _3 #-} instance Field3 (a,b,c,d,e,f,g) (a,b,c',d,e,f,g) c c' where _3 k ~(a,b,c,d,e,f,g) = k c <&> \c' -> (a,b,c',d,e,f,g) {-# INLINE _3 #-} instance Field3 (a,b,c,d,e,f,g,h) (a,b,c',d,e,f,g,h) c c' where _3 k ~(a,b,c,d,e,f,g,h) = k c <&> \c' -> (a,b,c',d,e,f,g,h) {-# INLINE _3 #-} instance Field3 (a,b,c,d,e,f,g,h,i) (a,b,c',d,e,f,g,h,i) c c' where _3 k ~(a,b,c,d,e,f,g,h,i) = k c <&> \c' -> (a,b,c',d,e,f,g,h,i) {-# INLINE _3 #-} -- | Provide access to the 4th field of a tuple. class Field4 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 4th field of a tuple. _4 :: Lens s t a b default _4 :: (Generic s, Generic t, GIxed N3 (Rep s) (Rep t) a b) => Lens s t a b _4 = ix proxyN3 {-# INLINE _4 #-} instance Field4 (a,b,c,d) (a,b,c,d') d d' where _4 k ~(a,b,c,d) = k d <&> \d' -> (a,b,c,d') {-# INLINE _4 #-} instance Field4 (a,b,c,d,e) (a,b,c,d',e) d d' where _4 k ~(a,b,c,d,e) = k d <&> \d' -> (a,b,c,d',e) {-# INLINE _4 #-} instance Field4 (a,b,c,d,e,f) (a,b,c,d',e,f) d d' where _4 k ~(a,b,c,d,e,f) = k d <&> \d' -> (a,b,c,d',e,f) {-# INLINE _4 #-} instance Field4 (a,b,c,d,e,f,g) (a,b,c,d',e,f,g) d d' where _4 k ~(a,b,c,d,e,f,g) = k d <&> \d' -> (a,b,c,d',e,f,g) {-# INLINE _4 #-} instance Field4 (a,b,c,d,e,f,g,h) (a,b,c,d',e,f,g,h) d d' where _4 k ~(a,b,c,d,e,f,g,h) = k d <&> \d' -> (a,b,c,d',e,f,g,h) {-# INLINE _4 #-} instance Field4 (a,b,c,d,e,f,g,h,i) (a,b,c,d',e,f,g,h,i) d d' where _4 k ~(a,b,c,d,e,f,g,h,i) = k d <&> \d' -> (a,b,c,d',e,f,g,h,i) {-# INLINE _4 #-} -- | Provides access to the 5th field of a tuple. class Field5 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 5th field of a tuple. _5 :: Lens s t a b default _5 :: (Generic s, Generic t, GIxed N4 (Rep s) (Rep t) a b) => Lens s t a b _5 = ix proxyN4 {-# INLINE _5 #-} instance Field5 (a,b,c,d,e) (a,b,c,d,e') e e' where _5 k ~(a,b,c,d,e) = k e <&> \e' -> (a,b,c,d,e') {-# INLINE _5 #-} instance Field5 (a,b,c,d,e,f) (a,b,c,d,e',f) e e' where _5 k ~(a,b,c,d,e,f) = k e <&> \e' -> (a,b,c,d,e',f) {-# INLINE _5 #-} instance Field5 (a,b,c,d,e,f,g) (a,b,c,d,e',f,g) e e' where _5 k ~(a,b,c,d,e,f,g) = k e <&> \e' -> (a,b,c,d,e',f,g) {-# INLINE _5 #-} instance Field5 (a,b,c,d,e,f,g,h) (a,b,c,d,e',f,g,h) e e' where _5 k ~(a,b,c,d,e,f,g,h) = k e <&> \e' -> (a,b,c,d,e',f,g,h) {-# INLINE _5 #-} instance Field5 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e',f,g,h,i) e e' where _5 k ~(a,b,c,d,e,f,g,h,i) = k e <&> \e' -> (a,b,c,d,e',f,g,h,i) {-# INLINE _5 #-} -- | Provides access to the 6th element of a tuple. class Field6 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 6th field of a tuple. _6 :: Lens s t a b default _6 :: (Generic s, Generic t, GIxed N5 (Rep s) (Rep t) a b) => Lens s t a b _6 = ix proxyN5 {-# INLINE _6 #-} instance Field6 (a,b,c,d,e,f) (a,b,c,d,e,f') f f' where _6 k ~(a,b,c,d,e,f) = k f <&> \f' -> (a,b,c,d,e,f') {-# INLINE _6 #-} instance Field6 (a,b,c,d,e,f,g) (a,b,c,d,e,f',g) f f' where _6 k ~(a,b,c,d,e,f,g) = k f <&> \f' -> (a,b,c,d,e,f',g) {-# INLINE _6 #-} instance Field6 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f',g,h) f f' where _6 k ~(a,b,c,d,e,f,g,h) = k f <&> \f' -> (a,b,c,d,e,f',g,h) {-# INLINE _6 #-} instance Field6 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f',g,h,i) f f' where _6 k ~(a,b,c,d,e,f,g,h,i) = k f <&> \f' -> (a,b,c,d,e,f',g,h,i) {-# INLINE _6 #-} -- | Provide access to the 7th field of a tuple. class Field7 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 7th field of a tuple. _7 :: Lens s t a b default _7 :: (Generic s, Generic t, GIxed N6 (Rep s) (Rep t) a b) => Lens s t a b _7 = ix proxyN6 {-# INLINE _7 #-} instance Field7 (a,b,c,d,e,f,g) (a,b,c,d,e,f,g') g g' where _7 k ~(a,b,c,d,e,f,g) = k g <&> \g' -> (a,b,c,d,e,f,g') {-# INLINE _7 #-} instance Field7 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g',h) g g' where _7 k ~(a,b,c,d,e,f,g,h) = k g <&> \g' -> (a,b,c,d,e,f,g',h) {-# INLINE _7 #-} instance Field7 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g',h,i) g g' where _7 k ~(a,b,c,d,e,f,g,h,i) = k g <&> \g' -> (a,b,c,d,e,f,g',h,i) {-# INLINE _7 #-} -- | Provide access to the 8th field of a tuple. class Field8 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 8th field of a tuple. _8 :: Lens s t a b default _8 :: (Generic s, Generic t, GIxed N7 (Rep s) (Rep t) a b) => Lens s t a b _8 = ix proxyN7 {-# INLINE _8 #-} instance Field8 (a,b,c,d,e,f,g,h) (a,b,c,d,e,f,g,h') h h' where _8 k ~(a,b,c,d,e,f,g,h) = k h <&> \h' -> (a,b,c,d,e,f,g,h') {-# INLINE _8 #-} instance Field8 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h',i) h h' where _8 k ~(a,b,c,d,e,f,g,h,i) = k h <&> \h' -> (a,b,c,d,e,f,g,h',i) {-# INLINE _8 #-} -- | Provides access to the 9th field of a tuple. class Field9 s t a b | s -> a, t -> b, s b -> t, t a -> s where -- | Access the 9th field of a tuple. _9 :: Lens s t a b default _9 :: (Generic s, Generic t, GIxed N8 (Rep s) (Rep t) a b) => Lens s t a b _9 = ix proxyN8 {-# INLINE _9 #-} instance Field9 (a,b,c,d,e,f,g,h,i) (a,b,c,d,e,f,g,h,i') i i' where _9 k ~(a,b,c,d,e,f,g,h,i) = k i <&> \i' -> (a,b,c,d,e,f,g,h,i') {-# INLINE _9 #-} -- Strict versions of the _1 .. _9 operations -- | Strict version of '_1' _1' :: Field1 s t a b => Lens s t a b _1' = \f !x -> _1 f x {-# INLINE _1' #-} -- | Strict version of '_2' _2' :: Field2 s t a b => Lens s t a b _2' = \f !x -> _2 f x {-# INLINE _2' #-} -- | Strict version of '_3' _3' :: Field3 s t a b => Lens s t a b _3' = \f !x -> _3 f x {-# INLINE _3' #-} -- | Strict version of '_4' _4' :: Field4 s t a b => Lens s t a b _4' = \f !x -> _4 f x {-# INLINE _4' #-} -- | Strict version of '_5' _5' :: Field5 s t a b => Lens s t a b _5' = \f !x -> _5 f x {-# INLINE _5' #-} -- | Strict version of '_6' _6' :: Field6 s t a b => Lens s t a b _6' = \f !x -> _6 f x {-# INLINE _6' #-} -- | Strict version of '_7' _7' :: Field7 s t a b => Lens s t a b _7' = \f !x -> _7 f x {-# INLINE _7' #-} -- | Strict version of '_8' _8' :: Field8 s t a b => Lens s t a b _8' = \f !x -> _8 f x {-# INLINE _8' #-} -- | Strict version of '_9' _9' :: Field9 s t a b => Lens s t a b _9' = \f !x -> _9 f x {-# INLINE _9' #-} ix :: (Generic s, Generic t, GIxed n (Rep s) (Rep t) a b) => f n -> Lens s t a b ix n f = fmap to . gix n f . from {-# INLINE ix #-} type family GSize (f :: * -> *) type instance GSize U1 = Z type instance GSize (K1 i c) = S Z type instance GSize (M1 i c f) = GSize f type instance GSize (a :*: b) = Add (GSize a) (GSize b) class GIxed n s t a b | n s -> a, n t -> b, n s b -> t, n t a -> s where gix :: f n -> Lens (s x) (t x) a b instance GIxed N0 (K1 i a) (K1 i b) a b where gix _ = dimap unK1 (fmap K1) {-# INLINE gix #-} instance GIxed n s t a b => GIxed n (M1 i c s) (M1 i c t) a b where gix n = dimap unM1 (fmap M1) . gix n {-# INLINE gix #-} instance (p ~ GT (GSize s) n, p ~ GT (GSize t) n, GIxed' p n s s' t t' a b) => GIxed n (s :*: s') (t :*: t') a b where gix = gix' (Proxy :: Proxy p) {-# INLINE gix #-} #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706 -- $gixed-fundeps -- >>> :set -XDeriveGeneric -XFlexibleInstances -XMultiParamTypeClasses -- >>> import GHC.Generics (Generic) -- >>> data Product a b = a :* b deriving Generic -- >>> instance Field1 (Product a b) (Product a' b) a a' -- >>> instance Field2 (Product a b) (Product a b') b b' #endif class (p ~ GT (GSize s) n, p ~ GT (GSize t) n) => GIxed' p n s s' t t' a b | p n s s' -> a , p n t t' -> b , p n s s' b -> t t' , p n t t' a -> s s' where gix' :: f p -> g n -> Lens ((s :*: s') x) ((t :*: t') x) a b instance (GT (GSize s) n ~ T, GT (GSize t) n ~ T, GIxed n s t a b) => GIxed' T n s s' t s' a b where gix' _ n f (s :*: s') = (:*: s') <$> gix n f s {-# INLINE gix' #-} instance (GT (GSize s) n ~ F, n' ~ Subtract (GSize s) n, GIxed n' s' t' a b) => GIxed' F n s s' s t' a b where gix' _ _ f (s :*: s') = (s :*:) <$> gix (Proxy :: Proxy n') f s' {-# INLINE gix' #-} data Z data S a data T data F type family Add x y type instance Add Z y = y type instance Add (S x) y = S (Add x y) type family Subtract x y type instance Subtract Z x = x type instance Subtract (S x) (S y) = Subtract x y type family GT x y type instance GT Z x = F type instance GT (S x) Z = T type instance GT (S x) (S y) = GT x y type N0 = Z type N1 = S N0 type N2 = S N1 type N3 = S N2 type N4 = S N3 type N5 = S N4 type N6 = S N5 type N7 = S N6 type N8 = S N7 proxyN0 :: Proxy N0 proxyN0 = Proxy {-# INLINE proxyN0 #-} proxyN1 :: Proxy N1 proxyN1 = Proxy {-# INLINE proxyN1 #-} proxyN2 :: Proxy N2 proxyN2 = Proxy {-# INLINE proxyN2 #-} proxyN3 :: Proxy N3 proxyN3 = Proxy {-# INLINE proxyN3 #-} proxyN4 :: Proxy N4 proxyN4 = Proxy {-# INLINE proxyN4 #-} proxyN5 :: Proxy N5 proxyN5 = Proxy {-# INLINE proxyN5 #-} proxyN6 :: Proxy N6 proxyN6 = Proxy {-# INLINE proxyN6 #-} proxyN7 :: Proxy N7 proxyN7 = Proxy {-# INLINE proxyN7 #-} proxyN8 :: Proxy N8 proxyN8 = Proxy {-# INLINE proxyN8 #-}