5441605ecf683910fda50e3ef6e2af9a4df98a1a
[ghc.git] / libraries / base / Data / Bifunctor.hs
1 {-# LANGUAGE Safe #-}
2 {-# LANGUAGE CPP #-}
3
4 -----------------------------------------------------------------------------
5 -- |
6 -- Module : Data.Bifunctor
7 -- Copyright : (C) 2008-2014 Edward Kmett,
8 -- License : BSD-style (see the file LICENSE)
9 --
10 -- Maintainer : libraries@haskell.org
11 -- Stability : provisional
12 -- Portability : portable
13 --
14 -- @since 4.8.0.0
15 ----------------------------------------------------------------------------
16 module Data.Bifunctor
17 ( Bifunctor(..)
18 ) where
19
20 import Control.Applicative ( Const(..) )
21 import GHC.Generics ( K1(..) )
22
23 -- | Formally, the class 'Bifunctor' represents a bifunctor
24 -- from @Hask@ -> @Hask@.
25 --
26 -- Intuitively it is a bifunctor where both the first and second
27 -- arguments are covariant.
28 --
29 -- You can define a 'Bifunctor' by either defining 'bimap' or by
30 -- defining both 'first' and 'second'.
31 --
32 -- If you supply 'bimap', you should ensure that:
33 --
34 -- @'bimap' 'id' 'id' ≡ 'id'@
35 --
36 -- If you supply 'first' and 'second', ensure:
37 --
38 -- @
39 -- 'first' 'id' ≡ 'id'
40 -- 'second' 'id' ≡ 'id'
41 -- @
42 --
43 -- If you supply both, you should also ensure:
44 --
45 -- @'bimap' f g ≡ 'first' f '.' 'second' g@
46 --
47 -- These ensure by parametricity:
48 --
49 -- @
50 -- 'bimap' (f '.' g) (h '.' i) ≡ 'bimap' f h '.' 'bimap' g i
51 -- 'first' (f '.' g) ≡ 'first' f '.' 'first' g
52 -- 'second' (f '.' g) ≡ 'second' f '.' 'second' g
53 -- @
54 --
55 -- @since 4.8.0.0
56 class Bifunctor p where
57 {-# MINIMAL bimap | first, second #-}
58
59 -- | Map over both arguments at the same time.
60 --
61 -- @'bimap' f g ≡ 'first' f '.' 'second' g@
62 bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
63 bimap f g = first f . second g
64
65 -- | Map covariantly over the first argument.
66 --
67 -- @'first' f ≡ 'bimap' f 'id'@
68 first :: (a -> b) -> p a c -> p b c
69 first f = bimap f id
70
71 -- | Map covariantly over the second argument.
72 --
73 -- @'second' ≡ 'bimap' 'id'@
74 second :: (b -> c) -> p a b -> p a c
75 second = bimap id
76
77
78 -- | @since 4.8.0.0
79 instance Bifunctor (,) where
80 bimap f g ~(a, b) = (f a, g b)
81
82 -- | @since 4.8.0.0
83 instance Bifunctor ((,,) x1) where
84 bimap f g ~(x1, a, b) = (x1, f a, g b)
85
86 -- | @since 4.8.0.0
87 instance Bifunctor ((,,,) x1 x2) where
88 bimap f g ~(x1, x2, a, b) = (x1, x2, f a, g b)
89
90 -- | @since 4.8.0.0
91 instance Bifunctor ((,,,,) x1 x2 x3) where
92 bimap f g ~(x1, x2, x3, a, b) = (x1, x2, x3, f a, g b)
93
94 -- | @since 4.8.0.0
95 instance Bifunctor ((,,,,,) x1 x2 x3 x4) where
96 bimap f g ~(x1, x2, x3, x4, a, b) = (x1, x2, x3, x4, f a, g b)
97
98 -- | @since 4.8.0.0
99 instance Bifunctor ((,,,,,,) x1 x2 x3 x4 x5) where
100 bimap f g ~(x1, x2, x3, x4, x5, a, b) = (x1, x2, x3, x4, x5, f a, g b)
101
102
103 -- | @since 4.8.0.0
104 instance Bifunctor Either where
105 bimap f _ (Left a) = Left (f a)
106 bimap _ g (Right b) = Right (g b)
107
108 -- | @since 4.8.0.0
109 instance Bifunctor Const where
110 bimap f _ (Const a) = Const (f a)
111
112 -- | @since 4.9.0.0
113 instance Bifunctor (K1 i) where
114 bimap f _ (K1 c) = K1 (f c)