{-# LANGUAGE TupleSections #-} -- | Extra functions for working with pairs and triples. -- Some of these functions are available in the "Control.Arrow" module, -- but here are available specialised to pairs. Some operations work on triples. module Data.Tuple.Extra( module Data.Tuple, -- * Specialised 'Arrow' functions first, second, (***), (&&&), -- * More pair operations dupe, both, -- * Monadic versions firstM, secondM, -- * Operations on triple fst3, snd3, thd3, first3, second3, third3, curry3, uncurry3 ) where import Data.Tuple import qualified Control.Arrow as Arrow infixr 3 ***, &&& -- | Update the first component of a pair. -- -- > first succ (1,"test") == (2,"test") first :: (a -> a') -> (a, b) -> (a', b) first :: (a -> a') -> (a, b) -> (a', b) first = (a -> a') -> (a, b) -> (a', b) forall (a :: * -> * -> *) b c d. Arrow a => a b c -> a (b, d) (c, d) Arrow.first -- | Update the second component of a pair. -- -- > second reverse (1,"test") == (1,"tset") second :: (b -> b') -> (a, b) -> (a, b') second :: (b -> b') -> (a, b) -> (a, b') second = (b -> b') -> (a, b) -> (a, b') forall (a :: * -> * -> *) b c d. Arrow a => a b c -> a (d, b) (d, c) Arrow.second -- | Update the first component of a pair. -- -- > firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")] firstM :: Functor m => (a -> m a') -> (a, b) -> m (a', b) firstM :: (a -> m a') -> (a, b) -> m (a', b) firstM a -> m a' f (a a,b b) = (,b b) (a' -> (a', b)) -> m a' -> m (a', b) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> a -> m a' f a a -- | Update the second component of a pair. -- -- > secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")] secondM :: Functor m => (b -> m b') -> (a, b) -> m (a, b') secondM :: (b -> m b') -> (a, b) -> m (a, b') secondM b -> m b' f (a a,b b) = (a a,) (b' -> (a, b')) -> m b' -> m (a, b') forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> b -> m b' f b b -- | Given two functions, apply one to the first component and one to the second. -- A specialised version of 'Control.Arrow.***'. -- -- > (succ *** reverse) (1,"test") == (2,"tset") (***) :: (a -> a') -> (b -> b') -> (a, b) -> (a', b') *** :: (a -> a') -> (b -> b') -> (a, b) -> (a', b') (***) = (a -> a') -> (b -> b') -> (a, b) -> (a', b') forall (a :: * -> * -> *) b c b' c'. Arrow a => a b c -> a b' c' -> a (b, b') (c, c') (Arrow.***) -- | Given two functions, apply both to a single argument to form a pair. -- A specialised version of 'Control.Arrow.&&&'. -- -- > (succ &&& pred) 1 == (2,0) (&&&) :: (a -> b) -> (a -> c) -> a -> (b, c) &&& :: (a -> b) -> (a -> c) -> a -> (b, c) (&&&) = (a -> b) -> (a -> c) -> a -> (b, c) forall (a :: * -> * -> *) b c c'. Arrow a => a b c -> a b c' -> a b (c, c') (Arrow.&&&) -- | Duplicate a single value into a pair. -- -- > dupe 12 == (12, 12) dupe :: a -> (a,a) dupe :: a -> (a, a) dupe a x = (a x,a x) -- | Apply a single function to both components of a pair. -- -- > both succ (1,2) == (2,3) both :: (a -> b) -> (a, a) -> (b, b) both :: (a -> b) -> (a, a) -> (b, b) both a -> b f (a x,a y) = (a -> b f a x, a -> b f a y) -- | Extract the 'fst' of a triple. fst3 :: (a,b,c) -> a fst3 :: (a, b, c) -> a fst3 (a a,b b,c c) = a a -- | Extract the 'snd' of a triple. snd3 :: (a,b,c) -> b snd3 :: (a, b, c) -> b snd3 (a a,b b,c c) = b b -- | Extract the final element of a triple. thd3 :: (a,b,c) -> c thd3 :: (a, b, c) -> c thd3 (a a,b b,c c) = c c -- | Converts an uncurried function to a curried function. curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d curry3 (a, b, c) -> d f a a b b c c = (a, b, c) -> d f (a a,b b,c c) -- | Converts a curried function to a function on a triple. uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d) uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d uncurry3 a -> b -> c -> d f ~(a a,b b,c c) = a -> b -> c -> d f a a b b c c -- | Update the first component of a triple. -- -- > first3 succ (1,1,1) == (2,1,1) first3 :: (a -> a') -> (a, b, c) -> (a', b, c) first3 :: (a -> a') -> (a, b, c) -> (a', b, c) first3 a -> a' f (a a,b b,c c) = (a -> a' f a a,b b,c c) -- | Update the second component of a triple. -- -- > second3 succ (1,1,1) == (1,2,1) second3 :: (b -> b') -> (a, b, c) -> (a, b', c) second3 :: (b -> b') -> (a, b, c) -> (a, b', c) second3 b -> b' f (a a,b b,c c) = (a a,b -> b' f b b,c c) -- | Update the third component of a triple. -- -- > third3 succ (1,1,1) == (1,1,2) third3 :: (c -> c') -> (a, b, c) -> (a, b, c') third3 :: (c -> c') -> (a, b, c) -> (a, b, c') third3 c -> c' f (a a,b b,c c) = (a a,b b,c -> c' f c c)