@@ -0,0 +1,272 @@
1+We aim for a format of Haskell code that minimizes the amount of changes
2+necessary when modifying a line. For instance the indentation of any
3+given fragment of code should not depend on the length of identifiers.
4+
5+```Haskell
6+longFunctionName :: a
7+ -> b
8+ -> c
9+ -> d
10+ -> (a, b, c, d)
11+```
12+
13+Renaming the function requires changing all the lines to
14+```Haskell
15+f :: a
16+ -> b
17+ -> c
18+ -> d
19+ -> (a, b, c, d)
20+```
21+
22+A preferred alternative is to format like
23+```Haskell
24+longFunctionName
25+ :: a
26+ -> b
27+ -> c
28+ -> d
29+ -> (a, b, c, d)
30+```
31+
32+We are grabbing some inspiration from
33+[Elm](https://elm-lang.org/docs/style-guide)
34+and
35+[Tweag's](https://github.com/tweag/guides/blob/master/style/Haskell.md)
36+style guides.
37+
38+### Function types
39+
40+Type and name fits in one line
41+```Haskell
42+functionName :: (C1, C2) => a -> b -> (a, b)
43+```
44+
45+Type and name don't fit in one line.
46+```Haskell
47+functionName
48+ :: (C1, C2, C3) => a -> b -> c -> d -> (a, b, c, d)
49+```
50+
51+Context, arguments and result don't fit in one line.
52+```Haskell
53+functionName
54+ :: (C1, C2, C3, C4, C5)
55+ => a -> b -> c -> d -> (a, b, c, d)
56+```
57+
58+Arguments and result don't fit in one line.
59+```Haskell
60+functionName
61+ :: (C1, C2, C3, C4, C5)
62+ => a
63+ -> b
64+ -> (a -> b -> c)
65+ -> (c -> d)
66+ -> (a, b, c, d)
67+```
68+
69+Arguments don't fit in one line.
70+```Haskell
71+functionName
72+ :: (C1, C2, C3, C4, C5)
73+ => a
74+ -> b
75+ -> (forall a.
76+ (C6, C7)
77+ => LongDataTypeName
78+ -> a
79+ -> AnotherLongDataTypeName
80+ -> b
81+ -> c
82+ )
83+ -> (c -> d)
84+ -> (a, b, c, d)
85+```
86+
87+Arguments don't fit in one line.
88+```Haskell
89+functionName
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+```
105+
106+### Expressions
107+
108+Fits a line.
109+```Haskell
110+f x y z = if x then y else z
111+```
112+
113+Doesn't fit a line.
114+```Haskell
115+f x y z =
116+ if x then longFunctionName y else anotherLongFunctionName z
117+```
118+
119+A lambda fits a line.
120+```Haskell
121+f = \x -> x
122+```
123+
124+A lambda doesn't fit the line.
125+```Haskell
126+f =
127+ \(LongPattern x) ->
128+ longFunctionName x
129+```
130+
131+Multiple lambdas don't fit the line.
132+```Haskell
133+f = \(LongPattern x) ->
134+ \(LongPattern2 y) ->
135+ longFunctionName x
136+```
137+
138+The lambda arguments don't fit the line.
139+```Haskell
140+f xs =
141+ forM xs $ \( LongPattern x
142+ , LongPattern2 y
143+ ) ->
144+ longFunctionName x
145+```
146+
147+The lambda arguments and the preceding expression don't fit the line.
148+```Haskell
149+f xs =
150+ forM xs $
151+ \( LongPattern x
152+ , LongPattern2 y
153+ , LongPattern3 z
154+ ) ->
155+ longFunctionName x y z
156+```
157+
158+`if` expression doesn't fit a line.
159+```Haskell
160+f x y z =
161+ if x then
162+ longFunctionName x y
163+ else
164+ anotherLongFunctionName x z
165+```
166+
167+`if` expression with monadic blocks
168+```Haskell
169+f x y z =
170+ if x then do
171+ longFunctionName1 x y
172+ longFunctionName2 x y
173+ else do
174+ anotherLongFunctionName1 x z
175+ anotherLongFunctionName2 x z
176+```
177+
178+Monadic blocks
179+```Haskell
180+f x y z = do
181+ functionName1 x y
182+ functionName2 x z
183+```
184+
185+`case` expression
186+```Haskell
187+f x y z = case
188+ Just w -> functionName x y w
189+ Nothing -> functionName x y z
190+```
191+
192+Branches of `case` expression don't fit a line.
193+```Haskell
194+f x y z = case
195+ Just w ->
196+ longFunctionName x y w
197+ Nothing ->
198+ anotherLongFunctionName x y z
199+```
200+
201+A list of arguments doesn't fit a line.
202+```Haskell
203+f
204+ (LongPattern x)
205+ (AnotherLongPattern y)
206+ =
207+ functionName x y
208+```
209+
210+Guards
211+```Haskell
212+f x y
213+ | x > y = True
214+ | otherwise = False
215+```
216+
217+The right-hand side of guards doesn't fit in a line.
218+```Haskell
219+f x y
220+ | x > y =
221+ longFunctionName y
222+ | otherwise =
223+ anotherLongFunctionName x
224+```
225+
226+Long guards don't fit the line.
227+```Haskell
228+function x y z w y
229+ | x > y
230+ , y > z
231+ , z > w
232+ , w > z
233+ =
234+ longFunctionName y
235+ | otherwise =
236+ anotherLongFunctionName x
237+```
238+
239+Long guards with monadic block
240+```Haskell
241+function x y z w y
242+ | x > y
243+ , y > z
244+ , z > w
245+ , w > z
246+ = do
247+ longFunctionName1 y
248+ longFunctionName2 y
249+ | otherwise = do
250+ anotherLongFunctionName1 x
251+ anotherLongFunctionName2 x
252+```
253+
254+### Data type declarations
255+
256+Declaration fits in one line.
257+```Haskell
258+data A = B | C | D
259+```
260+
261+Declaration doesn't fit in one line.
262+```Haskell
263+data A
264+ = B
265+ | C
266+ | D
267+ | E
268+ | F
269+ | G
270+```
271+
272+TODO: GADTs, record syntax, type families