|
|
1
|
+-- | This module is for convenience and demonstrative purposes
|
|
|
2
|
+-- more than it is for providing actual value.
|
|
|
3
|
+-- I do not recommend that you rely on this module
|
|
|
4
|
+-- for performance-sensitive code.
|
|
|
5
|
+-- Because this module is not based on Prelude's (.),
|
|
|
6
|
+-- some chances at optimization might be missed by your compiler.
|
|
|
7
|
+module Data.Composition (
|
|
|
8
|
+ -- * Math
|
|
|
9
|
+ (∘)
|
|
|
10
|
+
|
|
|
11
|
+ -- * Colons and dots
|
|
|
12
|
+ , (.:)
|
|
|
13
|
+ , (.:.)
|
|
|
14
|
+ , (.::)
|
|
|
15
|
+ , (.::.)
|
|
|
16
|
+ , (.:::)
|
|
|
17
|
+ , (.:::.)
|
|
|
18
|
+ , (.::::)
|
|
|
19
|
+ , (.::::.)
|
|
|
20
|
+
|
|
|
21
|
+ -- * Asterisks
|
|
|
22
|
+ , (.*)
|
|
|
23
|
+ , (.**)
|
|
|
24
|
+ , (.***)
|
|
|
25
|
+ , (.****)
|
|
|
26
|
+ , (.*****)
|
|
|
27
|
+ , (.******)
|
|
|
28
|
+ , (.*******)
|
|
|
29
|
+ , (.********)
|
|
|
30
|
+
|
|
|
31
|
+ -- * composeN
|
|
|
32
|
+ , compose1
|
|
|
33
|
+ , compose2
|
|
|
34
|
+ , compose3
|
|
|
35
|
+ , compose4
|
|
|
36
|
+ , compose5
|
|
|
37
|
+ , compose6
|
|
|
38
|
+ , compose7
|
|
|
39
|
+ , compose8
|
|
|
40
|
+ , compose9
|
|
|
41
|
+
|
|
|
42
|
+ ) where
|
|
|
43
|
+
|
|
|
44
|
+-- Not exported. This is defined here to remove the dependency on base
|
|
|
45
|
+(.) :: (b -> c) -> (a -> b) -> a -> c
|
|
|
46
|
+(f . g) x = f (g x)
|
|
|
47
|
+
|
|
|
48
|
+infixr 9 .
|
|
|
49
|
+
|
|
|
50
|
+-- | The mathematical symbol for function composition.
|
|
|
51
|
+(∘) :: (b -> c) -> (a -> b) -> a -> c
|
|
|
52
|
+(∘) = (.)
|
|
|
53
|
+
|
|
|
54
|
+infixr 9 ∘
|
|
|
55
|
+
|
|
|
56
|
+-- | Compose two functions. @f .: g@ is similar to @f . g@
|
|
|
57
|
+-- except that @g@ will be fed /two/ arguments instead of one
|
|
|
58
|
+-- before handing its result to @f@.
|
|
|
59
|
+--
|
|
|
60
|
+-- This function is defined as
|
|
|
61
|
+--
|
|
|
62
|
+-- > (f .: g) x y = f (g x y)
|
|
|
63
|
+--
|
|
|
64
|
+-- Example usage:
|
|
|
65
|
+--
|
|
|
66
|
+-- > concatMap :: (a -> [b]) -> [a] -> [b]
|
|
|
67
|
+-- > concatMap = concat .: map
|
|
|
68
|
+--
|
|
|
69
|
+-- Notice how /two/ arguments
|
|
|
70
|
+-- (the function /and/ the list)
|
|
|
71
|
+-- will be given to @map@ before the result
|
|
|
72
|
+-- is passed to @concat@. This is equivalent to:
|
|
|
73
|
+--
|
|
|
74
|
+-- > concatMap f xs = concat (map f xs)
|
|
|
75
|
+(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
|
|
|
76
|
+(f .: g) x y = f (g x y)
|
|
|
77
|
+
|
|
|
78
|
+infixr 8 .:
|
|
|
79
|
+
|
|
|
80
|
+-- | Equivalent to '.:'
|
|
|
81
|
+--
|
|
|
82
|
+-- The pattern of appending asterisks is
|
|
|
83
|
+-- straightforward to extend to similar functions:
|
|
|
84
|
+-- (compose2 = .*, compose3 = .**, etc).
|
|
|
85
|
+-- However, @.:@ has been commonly adopted amongst Haskellers,
|
|
|
86
|
+-- and the need for compose3 and beyond is rare in practice.
|
|
|
87
|
+(.*) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
|
|
|
88
|
+(.*) = (.) . (.)
|
|
|
89
|
+
|
|
|
90
|
+infixr 8 .*
|
|
|
91
|
+
|
|
|
92
|
+(.**) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
|
|
|
93
|
+(.**) = (.) . (.*)
|
|
|
94
|
+
|
|
|
95
|
+(.***) = (.) . (.**)
|
|
|
96
|
+(.****) = (.) . (.***)
|
|
|
97
|
+(.*****) = (.) . (.****)
|
|
|
98
|
+(.******) = (.) . (.*****)
|
|
|
99
|
+(.*******) = (.) . (.******)
|
|
|
100
|
+(.********) = (.) . (.*******)
|
|
|
101
|
+
|
|
|
102
|
+infixr 8 .**
|
|
|
103
|
+infixr 8 .***
|
|
|
104
|
+infixr 8 .****
|
|
|
105
|
+infixr 8 .*****
|
|
|
106
|
+infixr 8 .******
|
|
|
107
|
+infixr 8 .*******
|
|
|
108
|
+infixr 8 .********
|
|
|
109
|
+
|
|
|
110
|
+
|
|
|
111
|
+-- | @composeN f g@ means give @g@ @N@ inputs
|
|
|
112
|
+-- and then pass its result to @f@.
|
|
|
113
|
+compose1 :: (b -> c) -> (a -> b) -> a -> c
|
|
|
114
|
+compose1 = (.)
|
|
|
115
|
+
|
|
|
116
|
+compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
|
|
|
117
|
+compose2 = (.*)
|
|
|
118
|
+
|
|
|
119
|
+compose3 :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
|
|
|
120
|
+compose3 = (.**)
|
|
|
121
|
+
|
|
|
122
|
+compose4 = (.***)
|
|
|
123
|
+compose5 = (.****)
|
|
|
124
|
+compose6 = (.*****)
|
|
|
125
|
+compose7 = (.******)
|
|
|
126
|
+compose8 = (.*******)
|
|
|
127
|
+compose9 = (.********)
|
|
|
128
|
+
|
|
|
129
|
+-- | One compact pattern for composition operators is to
|
|
|
130
|
+-- "count the dots after the first one",
|
|
|
131
|
+-- which begins with the common '.:', and proceeds by first
|
|
|
132
|
+-- appending another @.@ and then replacing it with @:@
|
|
|
133
|
+(.:.) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
|
|
|
134
|
+(.:.) = (.**)
|
|
|
135
|
+
|
|
|
136
|
+(.::) = (.***)
|
|
|
137
|
+(.::.) = (.****)
|
|
|
138
|
+(.:::) = (.*****)
|
|
|
139
|
+(.:::.) = (.******)
|
|
|
140
|
+(.::::) = (.*******)
|
|
|
141
|
+(.::::.) = (.********)
|
|
|
142
|
+
|
|
|
143
|
+infixr 8 .:.
|
|
|
144
|
+infixr 8 .::
|
|
|
145
|
+infixr 8 .::.
|
|
|
146
|
+infixr 8 .:::
|
|
|
147
|
+infixr 8 .:::.
|
|
|
148
|
+infixr 8 .::::
|
|
|
149
|
+infixr 8 .::::.
|
|
|
150
|
+ |