on 2dfd181 help sign in
ormolu/EXAMPLES.md
296 lines 4.9 kB history raw
1We aim for a format of Haskell code that minimizes the amount of changes
2necessary when modifying a line. For instance the indentation of any
3given fragment of code should not depend on the length of identifiers.
5```Haskell
6longFunctionName :: a
7 -> b
8 -> c
9 -> d
10 -> (a, b, c, d)
11```
13Renaming the function requires changing all the lines to
14```Haskell
15f :: a
16 -> b
17 -> c
18 -> d
19 -> (a, b, c, d)
20```
22A preferred alternative is to format like
23```Haskell
24longFunctionName
25 :: a
26 -> b
27 -> c
28 -> d
29 -> (a, b, c, d)
30```
32We are grabbing some inspiration from
33[Elm](https://elm-lang.org/docs/style-guide)
34and
35[Tweag's](https://github.com/tweag/guides/blob/master/style/Haskell.md)
36style guides.
38The following examples show how a program is formatted in
39multiple lines when the user introduces linebreaks. Otherwise,
40the programs would be written in one line.
42### Function types
44```Haskell
45functionName
46 :: (C1, C2, C3)
47 => a
48 -> b
49 -> c
50 -> d
51 -> (a, b, c, d)
52```
54Context
55```Haskell
56functionName
57 :: ( C1
58 , C2
59 , C3
60 , C4
61 , C5
62 )
63 => a
64 -> b
65 -> c
66 -> d
67 -> (a, b, c, d)
68```
70Arguments
71```Haskell
72functionName
73 :: (C1, C2, C3, C4, C5)
74 => a
75 -> b
76 -> (forall a.
77 (C6, C7)
78 => LongDataTypeName
79 -> a
80 -> AnotherLongDataTypeName
81 -> b
82 -> c
83 )
84 -> (c -> d)
85 -> (a, b, c, d)
86```
88```Haskell
89functionName
90 :: (C1, C2, C3, C4, C5)
91 => a
92 -> b
93 -> ( LongDataTypeName
94 AnotherLongDataTypeName
95 AnotherLongDataTypeName2
96 AnotherLongDataTypeName3
97 -> a
98 -> AnotherLongDataTypeName4
99 -> b
100 -> c
101 )
102 -> (c -> d)
103 -> (a, b, c, d)
104```
106### Expressions
108```Haskell
109f x y z =
110 if x then longFunctionName y else anotherLongFunctionName z
111```
113A lambda
114```Haskell
115f =
116 \(LongPattern x) ->
117 longFunctionName x
118```
120Multiple lambdas
121```Haskell
122f =
123 \(LongPattern x) ->
124 \(LongPattern2 y) ->
125 longFunctionName x
126```
128Lambda arguments
129```Haskell
130f xs =
131 forM xs $
132 \( LongPattern x
133 , LongPattern2 y
134 ) ->
135 longFunctionName x
136```
138There is a do block. Note the change of indentation in the
139body of `forM`.
140```Haskell
141f xs = do
142 forM xs $
143 \( LongPattern x
144 , LongPattern2 y
145 ) ->
146 longFunctionName x
147```
149`if` expression
150```Haskell
151f x y z =
152 if x then
153 longFunctionName x y
154 else
155 anotherLongFunctionName x z
156```
158`if` expression with monadic blocks
159```Haskell
160f x y z =
161 if x then do
162 longFunctionName1 x y
163 longFunctionName2 x y
164 else do
165 anotherLongFunctionName1 x z
166 anotherLongFunctionName2 x z
167```
169Monadic blocks
170```Haskell
171f x y z = do
172 functionName1 x y
173 functionName2 x z
174```
176`case` expression
177```Haskell
178f x y z = case
179 Just w -> functionName x y w
180 Nothing -> functionName x y z
181```
183Branches of `case` expression
184```Haskell
185f x y z = case
186 Just w ->
187 longFunctionName x y w
188 Nothing ->
189 anotherLongFunctionName x y z
190```
192A list of arguments
193```Haskell
195 (LongPattern x)
196 (AnotherLongPattern y)
197 =
198 functionName x y
199```
201Guards
202```Haskell
203f x y
204 | x > y = True
205 | otherwise = False
206```
208The right-hand side of guards
209```Haskell
210f x y
211 | x > y =
212 longFunctionName y
213 | otherwise =
214 anotherLongFunctionName x
215```
217Long guards
218```Haskell
219function x y z w y
220 | x > y
221 , y > z
222 , z > w
223 , w > z
224 =
225 longFunctionName y
226 | otherwise =
227 anotherLongFunctionName x
228```
230### Data type declarations
232Declaration
233```Haskell
234data A
235 = B
236 | C
237 | D
238 | E
239 | F
240 | G
241```
243TODO: GADTs, record syntax, type families
245### Comments
247```Haskell
248{- When a comment is not preceded with elements on the same line,
249 they are indented as the elements in the enclosing AST node or
250 braces/parenthesis/brackets.
251 If it is between AST nodes, it is indented as the following
252 node.
253 If the end-of-file follows, then indent to column 0.
254-}
256f = g {- When there are preceding elements, keep single-line comments in the same line. -}
258h = g
259{- Multi-line comments can't be kept on the same line as @h = g@.
260 Otherwise, changing h or g would change the indentation of all
261 the comment lines.
262 -}
264data R = R
265 {- This comment always follows the R constructor -}
266 { f1 :: T1
267 {- A comment not preceded by other elements -}
268 {- Another comment -}
269 , f2 :: T2
270 , f3 :: T3
271 }
272```
274```Haskell
275{- a comment line -}
276f = h
277 where
278 h = g
279 -- indented the same as g
280 g = False
281```
283This example
284```Haskell
285data R = R {- This comment always follows the R constructor -}
286 { f1 :: T1, {- An inner comment -} {- Another inner comment -} f2 :: T2, f3 :: T3}
287```
288is reformatted to
289```Haskell
290data R = R
291 {- This comment always follows the R constructor -}
292 { f1 :: T1 {- An inner comment -} {- Another inner comment -}
293 , f2 :: T2
294 , f3 :: T3
295 }
296```