1{-# LANGUAGE TupleSections #-}
2
3-- | Extra functions for working with pairs and triples.
4--   Some of these functions are available in the "Control.Arrow" module,
5--   but here are available specialised to pairs. Some operations work on triples.
6module Data.Tuple.Extra(
7    module Data.Tuple,
8    -- * Specialised 'Arrow' functions
9    first, second, (***), (&&&),
10    -- * More pair operations
11    dupe, both,
12    -- * Monadic versions
13    firstM, secondM,
14    -- * Operations on triple
15    fst3, snd3, thd3,
16    curry3, uncurry3
17    ) where
18
19import Data.Tuple
20import qualified Control.Arrow as Arrow
21
22infixr 3 ***, &&&
23
24-- | Update the first component of a pair.
25--
26-- > first succ (1,"test") == (2,"test")
27first :: (a -> a') -> (a, b) -> (a', b)
28first = Arrow.first
29
30-- | Update the second component of a pair.
31--
32-- > second reverse (1,"test") == (1,"tset")
33second :: (b -> b') -> (a, b) -> (a, b')
34second = Arrow.second
35
36-- | Update the first component of a pair.
37--
38-- > firstM (\x -> [x-1, x+1]) (1,"test") == [(0,"test"),(2,"test")]
39firstM :: Functor m => (a -> m a') -> (a, b) -> m (a', b)
40firstM f (a,b) = (,b) <$> f a
41
42-- | Update the second component of a pair.
43--
44-- > secondM (\x -> [reverse x, x]) (1,"test") == [(1,"tset"),(1,"test")]
45secondM :: Functor m => (b -> m b') -> (a, b) -> m (a, b')
46secondM f (a,b) = (a,) <$> f b
47
48-- | Given two functions, apply one to the first component and one to the second.
49--   A specialised version of 'Control.Arrow.***'.
50--
51-- > (succ *** reverse) (1,"test") == (2,"tset")
52(***) :: (a -> a') -> (b -> b') -> (a, b) -> (a', b')
53(***) = (Arrow.***)
54
55-- | Given two functions, apply both to a single argument to form a pair.
56--   A specialised version of 'Control.Arrow.&&&'.
57--
58-- > (succ &&& pred) 1 == (2,0)
59(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
60(&&&) = (Arrow.&&&)
61
62-- | Duplicate a single value into a pair.
63--
64-- > dupe 12 == (12, 12)
65dupe :: a -> (a,a)
66dupe x = (x,x)
67
68-- | Apply a single function to both components of a pair.
69--
70-- > both succ (1,2) == (2,3)
71both :: (a -> b) -> (a, a) -> (b, b)
72both f (x,y) = (f x, f y)
73
74-- | Extract the 'fst' of a triple.
75fst3 :: (a,b,c) -> a
76fst3 (a,b,c) = a
77
78-- | Extract the 'snd' of a triple.
79snd3 :: (a,b,c) -> b
80snd3 (a,b,c) = b
81
82-- | Extract the final element of a triple.
83thd3 :: (a,b,c) -> c
84thd3 (a,b,c) = c
85
86-- | Converts an uncurried function to a curried function.
87curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
88curry3 f a b c = f (a,b,c)
89
90-- | Converts a curried function to a function on a triple.
91uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
92uncurry3 f ~(a,b,c) = f a b c
93