README.md
1# The rio library
2
3*A standard library for Haskell*
4
5![Rio](https://camo.githubusercontent.com/fc162fb0024699c85f00eae769085a5fe528153e/68747470733a2f2f7777772e61687374617469632e636f6d2f70686f746f732f636974792f76692d76363837315f30305f31343030783434322e6a7067)
6
7[![Build Status](https://dev.azure.com/snoyberg/rio/_apis/build/status/commercialhaskell.rio?branchName=master)](https://dev.azure.com/snoyberg/rio/_build/latest?definitionId=6&branchName=master)
8
9The goal of the `rio` library is to make it easier to adopt Haskell
10for writing production software. It is intended as a cross between:
11
12* Collection of well designed, trusted libraries
13* Useful `Prelude` replacement
14* A set of best practices for writing production quality Haskell code
15
16This repository contains the `rio` library and other related
17libraries, such as `rio-orphans`. There is a [tutorial on how to use
18`rio`](https://haskell.fpcomplete.com/library/rio) available on FP
19Complete's Haskell site. This README discusses project goals and
20collects other reference information.
21
22## Standard library
23
24While GHC ships with a `base` library, as well as a number of other
25common packages like `directory` and `transformers`, there are large
26gaps in functionality provided by these libraries. This choice for a
27more minimalistic `base` is by design, but it leads to some
28unfortunate consequences:
29
30* For a given task, it's often unclear which is the right library to
31 use
32* When writing libraries, there is often concern about adding
33 dependencies to any libraries outside of `base`, due to creating a
34 heavier dependency footprint
35* By avoiding adding dependencies, many libraries end up
36 reimplementing the same functionality, often with incompatible types
37 and type classes, leading to difficulty using libraries together
38
39This library attempts to define a standard library for Haskell. One
40immediate response may be [XKCD #927](https://xkcd.com/927/):
41
42![XKCD Standards](https://imgs.xkcd.com/comics/standards.png)
43
44To counter that effect, this library takes a specific approach: __it
45reuses existing, commonly used libraries__. Instead of defining an
46incompatible `Map` type, for instance, we standardize on the commonly
47used one from the `containers` library and reexport it from this
48library.
49
50This library attempts to define a set of libraries as "standard,"
51meaning they are recommended for use, and should be encouraged as
52dependencies for other libraries. It does this by depending on these
53libraries itself, and reexporting their types and functions for easy
54use.
55
56Beyond the ecosystem effects we hope to achieve, this will hopefully
57make the user story much easier. For a new user or team trying to get
58started, there is an easy library to depend upon for a large
59percentage of common functionality.
60
61See the dependencies of this package to see the list of packages
62considered standard. The primary interfaces of each of these packages
63is exposed from this library via a `RIO.`-prefixed module reexporting
64its interface.
65
66## Prelude replacement
67
68The `RIO` module works as a prelude replacement, providing more
69functionality and types out of the box than the standard prelude (such
70as common data types like `ByteString` and `Text`), as well as
71removing common "gotchas", like partial functions and lazy I/O. The
72guiding principle here is:
73
74* If something is safe to use in general and has no expected naming
75 conflicts, expose it from `RIO`
76* If something should not always be used, or has naming conflicts,
77 expose it from another module in the `RIO.` hierarchy.
78
79## Best practices
80
81Below is a set of best practices we recommend following. You're
82obviously free to take any, all, or none of this. Over time, these
83will probably develop into much more extensive docs. Some of these
84design decisions will be catered to by choices in the `rio` library.
85
86For Haskellers looking for a set of best practices to follow: you've
87come to the right place!
88
89### Import practices
90
91This library is intended to provide a fully loaded set of basic
92functionality. You should:
93
94* Enable the `NoImplicitPrelude` language extension (see below)
95* Add `import RIO` as your replacement prelude in all modules
96* Use the `RIO.`-prefixed modules as necessary, imported using the
97 recommended qualified names in the modules themselves. For example,
98 `import qualified RIO.ByteString as B`. See the module documentation
99 for more information.
100* Infix operators may be imported unqualified, with a separate import
101 line if necessary. For example, `import RIO.Map ((?!), (\\))`. Do
102 this only if your module contains no overlapping infix names,
103 regardless of qualification. For instance, if you are importing both
104 `RIO.Map.\\` and `RIO.List.\\` do not import either one unqualified.
105
106In the future, we may have editor integration or external tooling to
107help with import management.
108
109### Language extensions
110
111Very few projects these days use bare-bones Haskell 98
112or 2010. Instead, almost all codebases enable some set of additional
113language extensions. Below is a list of extensions we recommend as a
114good default, in that these are:
115
116* Well accepted in the community
117* Cause little to no code breakage versus leaving them off
118* Are generally considered safe
119
120Our recommended defaults are:
121
122```
123AutoDeriveTypeable
124BangPatterns
125BinaryLiterals
126ConstraintKinds
127DataKinds
128DefaultSignatures
129DeriveDataTypeable
130DeriveFoldable
131DeriveFunctor
132DeriveGeneric
133DeriveTraversable
134DoAndIfThenElse
135EmptyDataDecls
136ExistentialQuantification
137FlexibleContexts
138FlexibleInstances
139FunctionalDependencies
140GADTs
141GeneralizedNewtypeDeriving
142InstanceSigs
143KindSignatures
144LambdaCase
145MonadFailDesugaring
146MultiParamTypeClasses
147MultiWayIf
148NamedFieldPuns
149NoImplicitPrelude
150OverloadedStrings
151PartialTypeSignatures
152PatternGuards
153PolyKinds
154RankNTypes
155RecordWildCards
156ScopedTypeVariables
157StandaloneDeriving
158TupleSections
159TypeFamilies
160TypeSynonymInstances
161ViewPatterns
162```
163
164Notes on some surprising choices:
165
166* `RecordWildCards` is really up for debate. It's widely used, but
167 rightfully considered by many to be dangerous. Open question about
168 what we do with it.
169* Despite the fact that `OverloadedStrings` can break existing code,
170 we recommend its usage to encourage avoidance of the `String` data
171 type. Also, for new code, the risk of breakage is much lower.
172* `MonadFailDesugaring` helps prevent partial pattern matches in your
173 code, see [#85](https://github.com/commercialhaskell/rio/issues/85)
174
175Due to concerns about tooling usage (see [issue
176#9](https://github.com/commercialhaskell/rio/issues/9)), we recommend
177adding these extensions on-demand in your individual source modules
178instead of including them in your `package.yaml` or `.cabal` files.
179
180There are other language extensions which are perfectly fine to use as
181well, but are not recommended to be turned on by default:
182
183```
184CPP
185TemplateHaskell
186ForeignFunctionInterface
187MagicHash
188UnliftedFFITypes
189TypeOperators
190UnboxedTuples
191PackageImports
192QuasiQuotes
193DeriveAnyClass
194DeriveLift
195StaticPointers
196```
197
198### GHC Options
199
200We recommend using these GHC complier warning flags on all projects, to catch
201problems that might otherwise go overlooked:
202
203* `-Wall`
204* `-Wcompat`
205* `-Widentities`
206* `-Wincomplete-record-updates`
207* `-Wincomplete-uni-patterns`
208* `-Wpartial-fields`
209* `-Wredundant-constraints`
210
211You may add them per file, or to your `package.yaml`, or pass them on
212the command line when running ghc. We include these in the project
213template's `package.yaml` file.
214
215For code targeting production use, you should also use the flag that turns all
216warnings into errors, to force you to resolve the warnings before you ship your
217code:
218
219* `-Werror`
220
221Further reading:
222
223* Alexis King explains why these are a good idea in [her blog
224post](https://lexi-lambda.github.io/blog/2018/02/10/an-opinionated-guide-to-haskell-in-2018/)
225which was the original inspiration for this section.
226* Max Tagher gives an in-depth overview of these flags, and more,
227[in his blog post](https://medium.com/mercury-bank/enable-all-the-warnings-a0517bc081c3).
228
229### Monads
230
231A primary design choice you'll need to make in your code is how to
232structure your monads. There are many options out there, with various
233trade-offs. Instead of going through all of the debates, we're going
234to point to
235[an existing blog post](https://www.fpcomplete.com/blog/2017/07/the-rio-monad),
236and here just give recommendations.
237
238* If your code is going to perform I/O: it should live in the `RIO`
239 monad. `RIO` is "reader IO." It's the same as `ReaderT env IO`, but
240 includes some helper functions in this library and leads to nicer
241 type signatures and error messages.
242
243* If you need to provide access to specific data to a function, do it
244 via a typeclass constraint on the `env`, _not_ via a concrete
245 env. For example, this is bad:
246
247 ```haskell
248 myFunction :: RIO Config Foo
249 ```
250
251 This is good:
252
253 ```haskell
254 class HasConfig env where
255 configL :: Lens' env Config -- more on this in a moment
256 myFunction :: HasConfig env => RIO env Foo
257 ```
258
259 Reason: by using typeclass constraints on the environment, we can
260 easily compose multiple functions together and collect up the
261 constraints, which wouldn't be possible with concrete
262 environments. We _could_ go more general with mtl-style typeclasses,
263 like `MonadReader` or `MonadHasConfig`, but `RIO` is a perfect
264 balance point in the composability/concreteness space (see blog post
265 above for more details).
266
267* When defining `Has`-style typeclasses for the environments, we use
268 lenses (which are exposed by `RIO`) because it provides for easy
269 composability. We also leverage superclasses wherever possible. As
270 an example of how this works in practice:
271
272 ```haskell
273 -- Defined in RIO.Logger
274 class HasLogFunc env where
275 logFuncL :: Lens' env LogFunc
276
277 class HasConfig env where
278 configL :: Lens' env Config
279 instance HasConfig Config where
280 configL = id
281
282 data Env = Env { envLogFunc :: !LogFunc, envConfig :: !Config }
283 class (HasLogFunc env, HasConfig env) => HasEnv env where
284 envL :: Lens' env Env
285 instance HasLogFunc Env where
286 logFuncL = lens envLogFunc (\x y -> x { envLogFunc = y })
287 instance HasConfig Env where
288 configL = lens envConfig (\x y -> x { envConfig = y })
289 instance HasEnv Env where
290 envL = id
291
292 -- And then, at some other part of the code
293 data SuperEnv = SuperEnv { seEnv :: !Env, seOtherStuff :: !OtherStuff }
294 instance HasLogFunc SuperEnv where
295 logFuncL = envL.logFuncL
296 instance HasConfig SuperEnv where
297 configL = envL.configL
298 instance HasEnv SuperEnv where
299 envL = lens seEnv (\x y -> x { seEnv = y })
300 ```
301
302* If you're writing code that you want to be usable outside of `RIO`
303 for some reason, you should stick to the good mtl-style typeclasses:
304 `MonadReader`, `MonadIO`, `MonadUnliftIO`, `MonadThrow`, and
305 `PrimMonad`. It's better to use `MonadReader`+`Has` than to create
306 new typeclasses like `MonadLogger`, though usually just sticking
307 with the simpler `RIO env` is fine (and can easily be converted to
308 the more general form with `liftRIO`). You should avoid using the
309 following typeclasses (intentionally not exposed from this library):
310 `MonadBase`, `MonadBaseControl`, `MonadCatch`, and `MonadMask`.
311
312### Exceptions
313
314For in-depth discussion, see [safe exception
315handling](https://haskell.fpcomplete.com/tutorial/exceptions). The
316basic idea is:
317
318* If something can fail, and you want people to deal with that failure
319 every time (e.g., `lookup`), then return a `Maybe` or `Either`
320 value.
321* If the user will usually not want to deal with it, then use
322 exceptions. In the case of pure code, use a `MonadThrow`
323 constraint. In the case of `IO` code: use runtime exceptions via
324 `throwIO` (works in the `RIO` monad too).
325* You'll be upset and frustrated that you don't know exactly how some
326 `IO` action can fail. Accept that pain, live with it, internalize
327 it, use `tryAny`, and move on. It's the price we pay for async
328 exceptions.
329* Do all resource allocations with functions like `bracket` and
330 `finally`.
331
332It’s a good idea to define an app-wide exception type:
333
334```haskell
335data AppExceptions
336 = NetworkChangeError Text
337 | FilePathError FilePath
338 | ImpossibleError
339 deriving (Typeable)
340
341instance Exception AppExceptions
342
343instance Show AppExceptions where
344 show =
345 \case
346 NetworkChangeError err -> "network error: " <> (unpack err)
347 FilePathError fp -> "error accessing filepath at: " <> fp
348 ImpossibleError -> "this codepath should never have been executed. Please report a bug."
349```
350
351### Strict data fields
352
353Make data fields strict by default, unless you have a good reason to
354do otherwise.
355
356### Project template
357
358We provide a project template which sets up lots of things for you out
359of the box. You can use it by running:
360
361```
362$ stack new projectname rio
363```
364
365### Safety first
366
367This library intentionally puts safety first, and therefore avoids
368promoting partial functions and lazy I/O. If you think you need lazy
369I/O: you need a streaming data library like conduit instead.
370
371### When to generalize
372
373A common question in Haskell code is when should you generalize. Here
374are some simple guidelines. For parametric polymorphism: _almost
375always_ generalize, it makes your type signatures more informative and
376functions more useful. In other words, `reverse :: [a] -> [a]` is far
377better than `reverse :: [Int] -> [Int]`.
378
379When it comes to typeclasses: the story is more nuanced. For
380typeclasses provided by `RIO`, like `Foldable` or `Traversable`, it's
381generally a good thing to generalize to them when possible. The real
382question is defining your own typeclasses. As a general rule: avoid
383doing so as long as possible. And _if_ you define a typeclass: make
384sure its usage can't lead to accidental bugs by allowing you to swap
385in types you didn't expect.
386
387### Module hierarchy
388
389The `RIO.Prelude.` module hierarchy contains identifiers which are reexported
390by the `RIO` module. The reason for this is to make it easier to view the
391generated Haddocks. The `RIO` module itself is intended to be imported
392unqualified, with `NoImplicitPrelude` enabled. All other modules are _not_
393reexported by the `RIO` module,
394and will document inside of them whether they should be imported qualified or
395unqualified.
396