diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog for harg
 
+## 0.4.1.0 [2019.12.22]
+
+- Parsers now stop immediately if a source error is encountered
+- Updated the JSON source to return a bytestring instead of an `aeson` `Value`
+- Fix broken deriving for `barbie` typeclasses by re-exporting `Rec`
+
 ## 0.4.0.0 [2019.09.16]
 
 - Fix wrong name in previous release (`HasDefaultValStr` -> `HasDefaultStr`)
@@ -8,10 +14,11 @@
 
 ## 0.3.0.0 [2019.09.16]
 
-- Remove `*With` variants of option constructors and make the `*With` variant behaviour the default
-  (meaning now options are constructed using function composition and not `toOpt`)
-- Remove `opt` prefix from modifiers. Because `default` is a reserved keyword, this is now named
-  `defaultVal` (to mirror `defaultStr`)
+- Remove `*With` variants of option constructors and make the `*With` variant
+  behaviour the default (meaning now options are constructed using function
+  composition and not `toOpt`)
+- Remove `opt` prefix from modifiers. Because `default` is a reserved keyword,
+  this is now named `defaultVal` (to mirror `defaultStr`)
 
   NOTE: the above introduce breaking changes
 
@@ -19,8 +26,8 @@
 
 - Trigger a parser failure when any option in the sources fails to parse
 
-  NOTE: this introduces a breaking change, in that some parsers that failed silently
-        and selected the default (if applicable) will now fail.
+  NOTE: this introduces a breaking change, in that some parsers that failed
+        silently and selected the default (if applicable) will now fail.
 
 ## 0.1.3.0 [2019.08.28]
 
@@ -28,11 +35,13 @@
 
 ## 0.1.2.0 [2019.08.19]
 
-- Add `optRequired` (renamed to `required` for 0.3.0.0) to mark option as required
+- Add `optRequired` (renamed to `required` for 0.3.0.0) to mark option as
+  required
 
 ## 0.1.1.0 [2019.08.16]
 
-- Add `optDefaultStr` (renamed to `defaultStr` for 0.3.0.0) to provide defaults as unparsed strings
+- Add `optDefaultStr` (renamed to `defaultStr` for 0.3.0.0) to provide defaults
+  as unparsed strings
 - Bump dependencies (`barbies` and `higgledy`)
 
 ## 0.1.0.1 [2019.07.19]
diff --git a/README.lhs b/README.lhs
--- a/README.lhs
+++ b/README.lhs
@@ -1,25 +1,27 @@
-# harg
+# `harg`
 
 [![Build Status](https://travis-ci.org/alexpeits/harg.svg?branch=master)](https://travis-ci.org/alexpeits/harg)
 [![Hackage](https://img.shields.io/hackage/v/harg.svg)](https://hackage.haskell.org/package/harg)
 
-`harg` is a library for configuring programs by scanning command line arguments, environment
-variables, default values and more. Under the hood, it uses a subset of
-[`optparse-applicative`](https://hackage.haskell.org/package/optparse-applicative) to expose regular
-arguments, switch arguments and subcommands. The library relies heavily on the use of higher kinded
-data (HKD) thanks to the [`barbies`](https://hackage.haskell.org/package/barbies) library. Using
-[`higgledy`](https://hackage.haskell.org/package/higgledy) also allows to have significantly less
-boilerplate code.
+`harg` is a library for configuring programs by scanning command line arguments,
+environment variables, default values and more. Under the hood, it uses a subset
+of [`optparse-applicative`](https://hackage.haskell.org/package/optparse-applicative)
+to expose regular arguments, switch arguments and subcommands. The library
+relies heavily on the use of higher kinded data (HKD) thanks to the
+[`barbies`](https://hackage.haskell.org/package/barbies) library. Using
+[`higgledy`](https://hackage.haskell.org/package/higgledy) also allows to have
+significantly less boilerplate code.
 
-The main goal while developing `harg` was to not have to go through the usual pattern of manually
-`mappend`ing the results of command line parsing, env vars and defaults.
+The main goal while developing `harg` was to not have to go through the usual
+pattern of manually `mappend`ing the results of command line parsing, env vars
+and defaults.
 
 # Usage
 
 tl;dr: Take a look at the [example](Example.hs).
 
-Here are some different usage scenarios. Let's first enable some language extensions and add some
-imports:
+Here are some different usage scenarios. Let's first enable some language
+extensions and add some imports:
 
 ``` haskell
 {-# LANGUAGE DataKinds          #-}
@@ -48,8 +50,8 @@
 
 ## One flat (non-nested) datatype
 
-The easiest scenario is when the target configuration type is one single record with no levels of
-nesting:
+The easiest scenario is when the target configuration type is one single record
+with no levels of nesting:
 
 ``` haskell
 data FlatConfig
@@ -64,8 +66,8 @@
 
 (The `Generic` instance is required for section `3` later on)
 
-Let's first create the `Opt`s for each value in `FlatConfig`. `Opt` is the description for each
-component of the configuration.
+Let's first create the `Opt`s for each value in `FlatConfig`. `Opt` is the
+description for each component of the configuration.
 
 ``` haskell
 dbHostOpt :: Opt String
@@ -101,21 +103,24 @@
       )
 ```
 
-Here, we use `option` to define a command line argument that expects a value after it, `argument` to
-define a standalone argument, not prefixed by a long or short indicator, and `switch` to define a
-boolean command line flag that, if present, sets the target value to `True`. The `opt*` functions
-(here applied using `&` to make things look more declarative) modify the option configuration.
-`help` adds help text, `defaultVal` adds a default value, `short` adds a short command line
-option as an alternative to the long one (the string after `option` or `switch`), `envVar` sets
-the associated environment variable and `metavar` sets the metavariable to be shown in the help
-text generated by `optparse-applicative`.
+Here, we use `option` to define a command line argument that expects a value
+after it, `argument` to define a standalone argument, not prefixed by a long or
+short indicator, and `switch` to define a boolean command line flag that, if
+present, sets the target value to `True`. The `opt*` functions (here applied
+using `&` to make things look more declarative) modify the option configuration.
+`help` adds help text, `defaultVal` adds a default value, `short` adds a short
+command line option as an alternative to the long one (the string after `option`
+or `switch`), `envVar` sets the associated environment variable and `metavar`
+sets the metavariable to be shown in the help text generated by
+`optparse-applicative`.
 
 
-The first argument (`strParser` or `readParser`) is the parser for the argument, be it from the
-command line or from an environment variable. The type of this function should be
-`String -> Either String a`, which produces an error message or the parsed value. `strParser` is
-equivalent to `pure` and always succeeds. `readParser` requires the type to have a `Read` constraint.
-In order to use it with newtypes that wrap a type that has a `Read` constraint, using the `Functor`
+The first argument (`strParser` or `readParser`) is the parser for the argument,
+be it from the command line or from an environment variable. The type of this
+function should be `String -> Either String a`, which produces an error message
+or the parsed value. `strParser` is equivalent to `pure` and always succeeds.
+`readParser` requires the type to have a `Read` constraint. In order to use it
+with newtypes that wrap a type that has a `Read` constraint, using the `Functor`
 instance for `Opt` should be sufficient. E.g. for the newtype:
 
 ``` haskell
@@ -130,14 +135,16 @@
   = Port <$> dbPortOpt
 ```
 
-Of course, any user-defined function works as well. In addition, to use a function of type `String
--> Maybe a` use `parseWith`, which runs the parser and in case of failure uses a default error
-message. For example, `readParser` is defined as `parseWith readMaybe`.
+Of course, any user-defined function works as well. In addition, to use a
+function of type `String -> Maybe a` use `parseWith`, which runs the parser and
+in case of failure uses a default error message. For example, `readParser` is
+defined as `parseWith readMaybe`.
 
-Finally, an optional option with type `a` can be specified by setting its type to `Maybe a`. The
-declaration is exactly the same as it would be for `a`, and adding `optional` to the modifiers
-turns turns the parser from `String -> Either String a` to `String -> Either String (Maybe a)` but
-without using the `Read` instance for `Maybe`:
+Finally, an optional option with type `a` can be specified by setting its type
+to `Maybe a`. The declaration is exactly the same as it would be for `a`, and
+adding `optional` to the modifiers turns turns the parser from `String -> Either
+String a` to `String -> Either String (Maybe a)` but without using the `Read`
+instance for `Maybe`:
 
 ``` haskell ignore
 someOpt :: Opt (Maybe Int)
@@ -148,16 +155,16 @@
       )
 ```
 
-Note that `optional` can't be used with `defaultVal`. Using them together raises a type error at
-compile time, to ensure there's no ambiguous behaviour (e.g. the order of declaration of modifiers
-should not influence the resulting option).
+Note that `optional` can't be used with `defaultVal`. Using them together raises
+a type error at compile time, to ensure there's no ambiguous behaviour (e.g. the
+order of declaration of modifiers should not influence the resulting option).
 
 There are 3 ways to configure this datatype.
 
 ### 1. Using a `barbie` type
 
-`barbie` types are types of kind `(Type -> Type) -> Type`. The `barbie` type for `FlatConfig`
-looks like this:
+`barbie` types are types of kind `(Type -> Type) -> Type`. The `barbie` type for
+`FlatConfig` looks like this:
 
 ``` haskell
 data FlatConfigB f
@@ -170,12 +177,13 @@
   deriving (Generic, B.FunctorB, B.TraversableB, B.ProductB)
 ```
 
-I also derived some required instances that come from the `barbies` package. These instances allow
-us to change the `f` (`bmap` from `FunctorB`) and traverse all types in the record producing side
-effects (`btraverse` from `TraversableB`).
+I also derived some required instances that come from the `barbies` package.
+These instances allow us to change the `f` (`bmap` from `FunctorB`) and traverse
+all types in the record producing side effects (`btraverse` from
+`TraversableB`).
 
-Now let's define the value of this datatype, which holds our option configuration. The type
-constructor needed for the options is `Opt`:
+Now let's define the value of this datatype, which holds our option
+configuration. The type constructor needed for the options is `Opt`:
 
 ``` haskell
 flatConfigOpt1 :: FlatConfigB Opt
@@ -183,8 +191,8 @@
   = FlatConfigB dbHostOpt dbPortOpt dirOpt logOpt
 ```
 
-Because `dbHostOpt`, `dbPortOpt` and `logOpt` all have type `Opt <actual type>`, `flatConfigOpt1`
-has the correct type according to `FlatConfigB Opt`.
+Because `dbHostOpt`, `dbPortOpt` and `logOpt` all have type `Opt <actual type>`,
+`flatConfigOpt1` has the correct type according to `FlatConfigB Opt`.
 
 Now to actually run things:
 
@@ -192,48 +200,62 @@
 getFlatConfig1 :: IO ()
 getFlatConfig1 = do
   FlatConfigB host port dir log <- execOptDef flatConfigOpt1
-  print $ runIdentity (FlatConfig <$> host <*> port <*> dir <*> log)
+  print $ runIdentity $
+    FlatConfig
+    <$> host
+    <*> port
+    <*> dir
+    <*> log
 ```
 
-`execOpt` returns an `Identity x` where `x` is the type of the options we are configuring, in this
-case `FlatConfigB`. Here, we pattern match on the barbie-type, and then use the `Applicative`
-instance of `Identity` to get back an `Identity FlatConfig`.
+`execOpt` returns an `Identity x` where `x` is the type of the options we are
+configuring, in this case `FlatConfigB`. Here, we pattern match on the
+barbie-type, and then use the `Applicative` instance of `Identity` to get back
+an `Identity FlatConfig`.
 
 This is still a bit boilerplate-y. Let's look at another way.
 
 ### 2. Using a product type
 
-Looking at `FlatConfigB`, it's only used because of it's `barbie`-like capabilities. Other than that
-it's just a simple product type with the additional `f` before all its sub-types.
+Looking at `FlatConfigB`, it's only used because of it's `barbie`-like
+capabilities. Other than that it's just a simple product type with the
+additional `f` before all its sub-types.
 
-`harg` defines a type almost similar to `Product` (from `Data.Functor.Product`), which works in a
-similar fashion as servant's `:<|>` type. This type is defined in `Options.Harg.Het.Prod` and is
-called `:*` (the `*` stands for product). This type stores barbie-like types and also keeps the `f`
-handy: `data (a :* b) f = a f :* b f`. This is also easily made an instance of `Generic`,
-`FunctorB`, `TraversableB` and `ProductB`. With all that, let's rewrite the options value and the
-function to get the configuration:
+`harg` defines a type almost similar to `Product` (from `Data.Functor.Product`),
+which works in a similar fashion as servant's `:<|>` type. This type is defined
+in `Options.Harg.Het.Prod` and is called `:*` (the `*` stands for product). This
+type stores barbie-like types and also keeps the `f` handy: `data (a :* b) f = a
+f :* b f`. This is also easily made an instance of `Generic`, `FunctorB`,
+`TraversableB` and `ProductB`. With all that, let's rewrite the options value
+and the function to get the configuration:
 
 ``` haskell
-flatConfigOpt2 :: (Single String :* Single Int :* Single String :* Single Bool) Opt
 flatConfigOpt2
+  :: (Single String :* Single Int :* Single String :* Single Bool) Opt
+flatConfigOpt2
   = single dbHostOpt :* single dbPortOpt :* single dirOpt :* single logOpt
 
 getFlatConfig2 :: IO ()
 getFlatConfig2 = do
   host :* port :* dir :* log <- execOptDef flatConfigOpt2
-  print $ runIdentity
-    (FlatConfig <$> getSingle host <*> getSingle port <*> getSingle dir <*> getSingle log)
+  print $ runIdentity $
+    FlatConfig
+    <$> getSingle host
+    <*> getSingle port
+    <*> getSingle dir
+    <*> getSingle log
 ```
 
-This looks aufully similar to the previous version, but without having to write another datatype and
-derive all the instances. `:*` is both a type-level constructor and a value-level function that acts
-like list's `:`. It is also right-associative, so for example `a :* b :* c` is the same as
-`a :* (b :* c)`.
+This looks aufully similar to the previous version, but without having to write
+another datatype and derive all the instances. `:*` is both a type-level
+constructor and a value-level function that acts like list's `:`. It is also
+right-associative, so for example `a :* b :* c` is the same as `a :* (b :* c)`.
 
-The `Single` type constructor is used when talking about a single value, rather than a nested
-datatype. `Single a f` is a simple newtype over `f a`. The reason for using that is simply to switch
-the order of application, so that we can later apply the `f` (here `Opt`) to the compound type
-(`:*`). This makes type definitions look more similar to datatype definitions:
+The `Single` type constructor is used when talking about a single value, rather
+than a nested datatype. `Single a f` is a simple newtype over `f a`. The reason
+for using that is simply to switch the order of application, so that we can
+later apply the `f` (here `Opt`) to the compound type (`:*`). This makes type
+definitions look more similar to datatype definitions:
 
 ``` haskell
 type FlatConfigOpt2
@@ -242,10 +264,12 @@
   :* Single Bool
 ```
 
-In addition, `single` is used to wrap an `f a` into a `Single a f`, and `getSingle` is used
-to unwrap it. Later on we'll see how to construct nested configurations using `Nested`.
+In addition, `single` is used to wrap an `f a` into a `Single a f`, and
+`getSingle` is used to unwrap it. Later on we'll see how to construct nested
+configurations using `Nested`.
 
-However, the real value when having flat datatypes comes from the ability to use `higgledy`.
+However, the real value when having flat datatypes comes from the ability to use
+`higgledy`.
 
 ### 3. Using `HKD` from `higgledy`
 
@@ -260,14 +284,16 @@
   print $ runIdentity (construct result)
 ```
 
-This is the most straightforward way to work with flat configuration types. The `build` function
-takes as arguments the options (`Opt a` where `a` is each type in `FlatConfig`) **in the order they
-appear in the datatype**, and returns the generic representation of a type that's exactly the same
-as `FlatConfigB`. This means that we get all the `barbie` instances for free.
+This is the most straightforward way to work with flat configuration types. The
+`build` function takes as arguments the options (`Opt a` where `a` is each type
+in `FlatConfig`) **in the order they appear in the datatype**, and returns the
+generic representation of a type that's exactly the same as `FlatConfigB`. This
+means that we get all the `barbie` instances for free.
 
-To go back from the `HKD` representation of a datatype to the base one, we use `construct`.
-`construct` uses the applicative instance of the `f` which wraps each type in `FlatConfig` to give
-back an `f FlatConfig` (in our case an `Identity FlatConfig`).
+To go back from the `HKD` representation of a datatype to the base one, we use
+`construct`. `construct` uses the applicative instance of the `f` which wraps
+each type in `FlatConfig` to give back an `f FlatConfig` (in our case an
+`Identity FlatConfig`).
 
 ## Nested datatypes
 
@@ -343,8 +369,9 @@
   deriving (Generic, B.FunctorB, B.TraversableB, B.ProductB)
 ```
 
-To define the option parser, we need option parsers for every type inside it. This was true for
-flat configs too, but we have to manually construct a `DbConfigB Opt` and `ServiceConfigB Opt`:
+To define the option parser, we need option parsers for every type inside it.
+This was true for flat configs too, but we have to manually construct a
+`DbConfigB Opt` and `ServiceConfigB Opt`:
 
 ``` haskell
 configOpt1 :: ConfigB Opt
@@ -365,18 +392,24 @@
 ``` haskell
 getConfig1 :: IO ()
 getConfig1 = do
-  ConfigB (DbConfigB dbHost dbPort) (ServiceConfigB port log) dir <- execOptDef configOpt1
+  ConfigB (DbConfigB dbHost dbPort) (ServiceConfigB port log) dir <-
+    execOptDef configOpt1
   let
     db      = DbConfig <$> dbHost <*> dbPort
     service = ServiceConfig <$> port <*> log
-  print $ runIdentity (Config <$> db <*> service <*> dir)
+  print $ runIdentity $
+    Config
+    <$> db
+    <*> service
+    <*> dir
 ```
 
 ### 2. Using `higgledy`
 
-`higgledy` puts an `f` before every type, so doing something like `HKD Config f` doesn't make sense:
-looking at `ConfigB` it seems like the `f` needs to go to the right hand side of the nested types.
-We can, however, avoid the boilerplate of defining `barbie` types for the nested datatypes:
+`higgledy` puts an `f` before every type, so doing something like `HKD Config f`
+doesn't make sense: looking at `ConfigB` it seems like the `f` needs to go to
+the right hand side of the nested types. We can, however, avoid the boilerplate
+of defining `barbie` types for the nested datatypes:
 
 ``` haskell
 data ConfigH f
@@ -406,14 +439,19 @@
 getConfig2 :: IO ()
 getConfig2 = do
   ConfigH db service dir <- execOptDef configOpt2
-  print $ runIdentity (Config <$> construct db <*> construct service <*> dir)
+  print $ runIdentity $
+    Config
+    <$> construct db
+    <*> construct service
+    <*> dir
 ```
 
 ### 2. Using products
 
-Recall from previously that there's the `Single` type which in general turns `f b` into `b f`. This
-means that, by using `Single` for the directory option, all `f`s are after their types, so we can
-just use `:*` instead of having to declare a new datatype:
+Recall from previously that there's the `Single` type which in general turns `f
+b` into `b f`. This means that, by using `Single` for the directory option, all
+`f`s are after their types, so we can just use `:*` instead of having to declare
+a new datatype:
 
 ``` haskell
 type ConfigP
@@ -428,11 +466,16 @@
 getConfig3 :: IO ()
 getConfig3 = do
   db :* service :* dir <- execOptDef configOpt3
-  print $ runIdentity (Config <$> construct db <*> construct service <*> getSingle dir)
+  print $ runIdentity $
+    Config
+    <$> construct db
+    <*> construct service
+    <*> getSingle dir
 ```
 
-And, to make things look more orthogonal, `harg` defines a type called `Nested`, which is exactly
-the same as `HKD`. There are functions that correspond to `build` and `construct`, too:
+And, to make things look more orthogonal, `harg` defines a type called `Nested`,
+which is exactly the same as `HKD`. There are functions that correspond to
+`build` and `construct`, too:
 
 ```
 Nested    <-> HKD
@@ -460,7 +503,11 @@
 getConfig4 :: IO ()
 getConfig4 = do
   db :* service :* dir <- execOptDef configOpt4
-  print $ runIdentity (Config <$> getNested db <*> getNested service <*> getSingle dir)
+  print $ runIdentity $
+    Config
+    <$> getNested db
+    <*> getNested service
+    <*> getSingle dir
 ```
 
 Pretty cool.
@@ -470,12 +517,13 @@
 `harg` also supports (somewhat limited) subcommands, again by using `optparse-applicative`
 underneath.
 
-Because of limitations with higher kinded data when it comes to sum types, `harg` uses a different
-way to define subcommands. `optparse-applicative` allows defining subcommands that result to the
-same type, which means the user needs to define a sum type, and each subcommand results in a
-different constructor. In contrast, `harg` defines subcommands that can return completely different
-types. Instead of the result being a sum type, where the user has to pattern match on constructors,
-the result is a `Variant`, which is defined (almost) like this:
+Because of limitations with higher kinded data when it comes to sum types,
+`harg` uses a different way to define subcommands. `optparse-applicative` allows
+defining subcommands that result to the same type, which means the user needs to
+define a sum type, and each subcommand results in a different constructor. In
+contrast, `harg` defines subcommands that can return completely different types.
+Instead of the result being a sum type, where the user has to pattern match on
+constructors, the result is a `Variant`, which is defined (almost) like this:
 
 ``` haskell
 data Variant (xs :: [Type]) where
@@ -483,10 +531,12 @@
   There :: Variant xs -> Variant (y ': xs)
 ```
 
-`Variant` is like a sum type which holds all the summands in a type-level list. Instead of pattern
-matching in `Left` or `Right` like when using `Either`, we pattern match on `Here x`, `There (Here x)`
-etc. For a pretty thorough introduction to `Variant` and more heterogeneous types, check out
-[this repo](https://github.com/i-am-tom/learn-me-a-haskell) by [i-am-tom](https://github.com/i-am-tom).
+`Variant` is like a sum type which holds all the summands in a type-level list.
+Instead of pattern matching in `Left` or `Right` like when using `Either`, we
+pattern match on `Here x`, `There (Here x)` etc. For a pretty thorough
+introduction to `Variant` and more heterogeneous types, check out
+[this repo](https://github.com/i-am-tom/learn-me-a-haskell) by
+[i-am-tom](https://github.com/i-am-tom).
 
 ``` haskell
 x :: Variant '[Int, Bool, Char]
@@ -509,10 +559,11 @@
 
 to hold a type-level list of `barbie` types and the `f` to wrap every type with.
 
-To define a type to be used in a subcommand parser we need the target type and the subcommand name,
-which is encoded as a type-level string `Symbol`. There's a handy way to define this. Suppose that
-the the `Config` type above is the configuration type when the command is `app` and another type,
-e.g.`TestConfig` is the configuration when the command is `test`:
+To define a type to be used in a subcommand parser we need the target type and
+the subcommand name, which is encoded as a type-level string `Symbol`. There's a
+handy way to define this. Suppose that the the `Config` type above is the
+configuration type when the command is `app` and another type, e.g.`TestConfig`
+is the configuration when the command is `test`:
 
 ``` haskell
 data TestConfig
@@ -562,8 +613,8 @@
   = configOpt4 :+ testConfigOpt :+ ANil
 ```
 
-The `ANil` here marks the end of the association list (which is a heterogeneous list that associates
-symbols with types).
+The `ANil` here marks the end of the association list (which is a heterogeneous
+list that associates symbols with types).
 
 Here's how to run this parser:
 
@@ -573,11 +624,16 @@
   result <- execCommandsDef subcommandOpt
   case result of
     HereF (db :* service :* dir)
-      -> print $ runIdentity
-       $ Config <$> getNested db <*> getNested service <*> getSingle dir
+      -> print $ runIdentity $
+           Config
+           <$> getNested db
+           <*> getNested service
+           <*> getSingle dir
     ThereF (HereF (foo :* bar))
-      -> print $ runIdentity
-       $ TestConfig <$> getSingle foo <*> getSingle bar
+      -> print $ runIdentity $
+           TestConfig
+           <$> getSingle foo
+           <*> getSingle bar
 ```
 
 Or use `fromVariantF`, which is similar to the `either` function:
@@ -588,12 +644,17 @@
   result <- execCommandsDef subcommandOpt
   fromVariantF result
     (\(db :* service :* dir)
-       -> print $ runIdentity
-       $ Config <$> getNested db <*> getNested service <*> getSingle dir
+       -> print $ runIdentity $
+            Config
+            <$> getNested db
+            <*> getNested service
+            <*> getSingle dir
     )
     (\(foo :* bar)
-       -> print $ runIdentity
-       $ TestConfig <$> getSingle foo <*> getSingle bar
+       -> print $ runIdentity $
+            TestConfig
+            <$> getSingle foo
+            <*> getSingle bar
     )
 ```
 
@@ -609,17 +670,18 @@
   -> r
 ```
 
-The signature will accept the appropriate number of functions depending on the length of the type
-level list.
+The signature will accept the appropriate number of functions depending on the
+length of the type level list.
 
 ## More than just environment variables
 
-You may have noticed the use of `execOptDef` and `execCommandsDef` in all of the examples up to now.
-There are actually more configurable versions of these, called `execOpt` and `execCommands`
-respectively. With these functions the user can select where to get options from. For example,
-`execOptDef` is a shorthand for `execOpt EnvSource`, which means that options will be fetched from
-environment variables only (along with the command line, which is always required, and defaults,
-which can be optionally provided by the user).
+You may have noticed the use of `execOptDef` and `execCommandsDef` in all of the
+examples up to now. There are actually more configurable versions of these,
+called `execOpt` and `execCommands` respectively. With these functions the user
+can select where to get options from. For example, `execOptDef` is a shorthand
+for `execOpt EnvSource`, which means that options will be fetched from
+environment variables only (along with the command line, which is always
+required, and defaults, which can be optionally provided by the user).
 
 The sources currently supported are environment variables, json and yaml files.
 
@@ -674,25 +736,25 @@
   = build @FlatConfig dbHostOpt dbPortOpt dirOpt logOpt
 ```
 
-To use the JSON source, a `FromJSON` instance is required. Thankfully that's easy, since
-`FlatConfig` has `Generic` instance:
+To use the JSON source, a `FromJSON` instance is required. Thankfully that's
+easy, since `FlatConfig` has `Generic` instance:
 
 ``` haskell
 instance FromJSON FlatConfig
 ```
 
-In `harg`, sources are defined as products (using `:*`) of options, which means that the definition
-of the sources is not very different than defining options! If we only needed the environment
-variable source, the options would be:
+In `harg`, sources are defined as products (using `:*`) of options, which means
+that the definition of the sources is not very different than defining options!
+If we only needed the environment variable source, the options would be:
 
 ``` haskell ignore
 envSource :: EnvSource Opt
 envSource = EnvSource
 ```
 
-There's no need to actually define an option for the environment because there's no meaningful
-configuration for this. To use the `EnvSource` along with a json config, we use the following
-option:
+There's no need to actually define an option for the environment because there's
+no meaningful configuration for this. To use the `EnvSource` along with a json
+config, we use the following option:
 
 ``` haskell
 sourceOpt :: (EnvSource :* JSONSource) Opt
@@ -708,8 +770,8 @@
           )
 ```
 
-Here, the type of the option for the JSON source is `ConfigFile`. This type is a wrapper around
-`FilePath`, which looks like this:
+Here, the type of the option for the JSON source is `ConfigFile`. This type is a
+wrapper around `FilePath`, which looks like this:
 
 ``` haskell ignore
 data ConfigFile
@@ -717,8 +779,8 @@
   | NoConfigFile
 ```
 
-This has the advantage that, if the user wants to specify an optional configuration file, they can
-simply say:
+This has the advantage that, if the user wants to specify an optional
+configuration file, they can simply say:
 
 ``` haskell
 jsonOpt :: Opt ConfigFile
@@ -732,17 +794,16 @@
 Also, because `ConfigFile` has an `IsString` instance, there's no need to say
 `long (ConfigFile "json")` (if `OverloadedStrings` is enabled).
 
-There's a bit of a disconnect between `ConfigFile` and the ability to make optional options using
-`Maybe` and `optional`. The reason for it is that the type that `JSONSource` wraps is not
-polymorphic, since it needs to be a filepath specifically.
+There's a bit of a disconnect between `ConfigFile` and the ability to make
+optional options using `Maybe` and `optional`. The reason for it is that the
+type that `JSONSource` wraps is not polymorphic, since it needs to be a filepath
+specifically.
 
 # Roadmap
 
 - Better errors using `optparse-applicative`'s internals
 - Allow user to pass `optparse-applicative` preferences
 - Write tests
-- ~~Be able to provide and get back the same type for multiple subcommands~~
-- ~~Integrate config files (e.g. JSON using aeson)~~
 
 # Credits
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,25 +1,27 @@
-# harg
+# `harg`
 
 [![Build Status](https://travis-ci.org/alexpeits/harg.svg?branch=master)](https://travis-ci.org/alexpeits/harg)
 [![Hackage](https://img.shields.io/hackage/v/harg.svg)](https://hackage.haskell.org/package/harg)
 
-`harg` is a library for configuring programs by scanning command line arguments, environment
-variables, default values and more. Under the hood, it uses a subset of
-[`optparse-applicative`](https://hackage.haskell.org/package/optparse-applicative) to expose regular
-arguments, switch arguments and subcommands. The library relies heavily on the use of higher kinded
-data (HKD) thanks to the [`barbies`](https://hackage.haskell.org/package/barbies) library. Using
-[`higgledy`](https://hackage.haskell.org/package/higgledy) also allows to have significantly less
-boilerplate code.
+`harg` is a library for configuring programs by scanning command line arguments,
+environment variables, default values and more. Under the hood, it uses a subset
+of [`optparse-applicative`](https://hackage.haskell.org/package/optparse-applicative)
+to expose regular arguments, switch arguments and subcommands. The library
+relies heavily on the use of higher kinded data (HKD) thanks to the
+[`barbies`](https://hackage.haskell.org/package/barbies) library. Using
+[`higgledy`](https://hackage.haskell.org/package/higgledy) also allows to have
+significantly less boilerplate code.
 
-The main goal while developing `harg` was to not have to go through the usual pattern of manually
-`mappend`ing the results of command line parsing, env vars and defaults.
+The main goal while developing `harg` was to not have to go through the usual
+pattern of manually `mappend`ing the results of command line parsing, env vars
+and defaults.
 
 # Usage
 
 tl;dr: Take a look at the [example](Example.hs).
 
-Here are some different usage scenarios. Let's first enable some language extensions and add some
-imports:
+Here are some different usage scenarios. Let's first enable some language
+extensions and add some imports:
 
 ``` haskell
 {-# LANGUAGE DataKinds          #-}
@@ -48,8 +50,8 @@
 
 ## One flat (non-nested) datatype
 
-The easiest scenario is when the target configuration type is one single record with no levels of
-nesting:
+The easiest scenario is when the target configuration type is one single record
+with no levels of nesting:
 
 ``` haskell
 data FlatConfig
@@ -64,8 +66,8 @@
 
 (The `Generic` instance is required for section `3` later on)
 
-Let's first create the `Opt`s for each value in `FlatConfig`. `Opt` is the description for each
-component of the configuration.
+Let's first create the `Opt`s for each value in `FlatConfig`. `Opt` is the
+description for each component of the configuration.
 
 ``` haskell
 dbHostOpt :: Opt String
@@ -101,21 +103,24 @@
       )
 ```
 
-Here, we use `option` to define a command line argument that expects a value after it, `argument` to
-define a standalone argument, not prefixed by a long or short indicator, and `switch` to define a
-boolean command line flag that, if present, sets the target value to `True`. The `opt*` functions
-(here applied using `&` to make things look more declarative) modify the option configuration.
-`help` adds help text, `defaultVal` adds a default value, `short` adds a short command line
-option as an alternative to the long one (the string after `option` or `switch`), `envVar` sets
-the associated environment variable and `metavar` sets the metavariable to be shown in the help
-text generated by `optparse-applicative`.
+Here, we use `option` to define a command line argument that expects a value
+after it, `argument` to define a standalone argument, not prefixed by a long or
+short indicator, and `switch` to define a boolean command line flag that, if
+present, sets the target value to `True`. The `opt*` functions (here applied
+using `&` to make things look more declarative) modify the option configuration.
+`help` adds help text, `defaultVal` adds a default value, `short` adds a short
+command line option as an alternative to the long one (the string after `option`
+or `switch`), `envVar` sets the associated environment variable and `metavar`
+sets the metavariable to be shown in the help text generated by
+`optparse-applicative`.
 
 
-The first argument (`strParser` or `readParser`) is the parser for the argument, be it from the
-command line or from an environment variable. The type of this function should be
-`String -> Either String a`, which produces an error message or the parsed value. `strParser` is
-equivalent to `pure` and always succeeds. `readParser` requires the type to have a `Read` constraint.
-In order to use it with newtypes that wrap a type that has a `Read` constraint, using the `Functor`
+The first argument (`strParser` or `readParser`) is the parser for the argument,
+be it from the command line or from an environment variable. The type of this
+function should be `String -> Either String a`, which produces an error message
+or the parsed value. `strParser` is equivalent to `pure` and always succeeds.
+`readParser` requires the type to have a `Read` constraint. In order to use it
+with newtypes that wrap a type that has a `Read` constraint, using the `Functor`
 instance for `Opt` should be sufficient. E.g. for the newtype:
 
 ``` haskell
@@ -130,14 +135,16 @@
   = Port <$> dbPortOpt
 ```
 
-Of course, any user-defined function works as well. In addition, to use a function of type `String
--> Maybe a` use `parseWith`, which runs the parser and in case of failure uses a default error
-message. For example, `readParser` is defined as `parseWith readMaybe`.
+Of course, any user-defined function works as well. In addition, to use a
+function of type `String -> Maybe a` use `parseWith`, which runs the parser and
+in case of failure uses a default error message. For example, `readParser` is
+defined as `parseWith readMaybe`.
 
-Finally, an optional option with type `a` can be specified by setting its type to `Maybe a`. The
-declaration is exactly the same as it would be for `a`, and adding `optional` to the modifiers
-turns turns the parser from `String -> Either String a` to `String -> Either String (Maybe a)` but
-without using the `Read` instance for `Maybe`:
+Finally, an optional option with type `a` can be specified by setting its type
+to `Maybe a`. The declaration is exactly the same as it would be for `a`, and
+adding `optional` to the modifiers turns turns the parser from `String -> Either
+String a` to `String -> Either String (Maybe a)` but without using the `Read`
+instance for `Maybe`:
 
 ``` haskell ignore
 someOpt :: Opt (Maybe Int)
@@ -148,16 +155,16 @@
       )
 ```
 
-Note that `optional` can't be used with `defaultVal`. Using them together raises a type error at
-compile time, to ensure there's no ambiguous behaviour (e.g. the order of declaration of modifiers
-should not influence the resulting option).
+Note that `optional` can't be used with `defaultVal`. Using them together raises
+a type error at compile time, to ensure there's no ambiguous behaviour (e.g. the
+order of declaration of modifiers should not influence the resulting option).
 
 There are 3 ways to configure this datatype.
 
 ### 1. Using a `barbie` type
 
-`barbie` types are types of kind `(Type -> Type) -> Type`. The `barbie` type for `FlatConfig`
-looks like this:
+`barbie` types are types of kind `(Type -> Type) -> Type`. The `barbie` type for
+`FlatConfig` looks like this:
 
 ``` haskell
 data FlatConfigB f
@@ -170,12 +177,13 @@
   deriving (Generic, B.FunctorB, B.TraversableB, B.ProductB)
 ```
 
-I also derived some required instances that come from the `barbies` package. These instances allow
-us to change the `f` (`bmap` from `FunctorB`) and traverse all types in the record producing side
-effects (`btraverse` from `TraversableB`).
+I also derived some required instances that come from the `barbies` package.
+These instances allow us to change the `f` (`bmap` from `FunctorB`) and traverse
+all types in the record producing side effects (`btraverse` from
+`TraversableB`).
 
-Now let's define the value of this datatype, which holds our option configuration. The type
-constructor needed for the options is `Opt`:
+Now let's define the value of this datatype, which holds our option
+configuration. The type constructor needed for the options is `Opt`:
 
 ``` haskell
 flatConfigOpt1 :: FlatConfigB Opt
@@ -183,8 +191,8 @@
   = FlatConfigB dbHostOpt dbPortOpt dirOpt logOpt
 ```
 
-Because `dbHostOpt`, `dbPortOpt` and `logOpt` all have type `Opt <actual type>`, `flatConfigOpt1`
-has the correct type according to `FlatConfigB Opt`.
+Because `dbHostOpt`, `dbPortOpt` and `logOpt` all have type `Opt <actual type>`,
+`flatConfigOpt1` has the correct type according to `FlatConfigB Opt`.
 
 Now to actually run things:
 
@@ -192,48 +200,62 @@
 getFlatConfig1 :: IO ()
 getFlatConfig1 = do
   FlatConfigB host port dir log <- execOptDef flatConfigOpt1
-  print $ runIdentity (FlatConfig <$> host <*> port <*> dir <*> log)
+  print $ runIdentity $
+    FlatConfig
+    <$> host
+    <*> port
+    <*> dir
+    <*> log
 ```
 
-`execOpt` returns an `Identity x` where `x` is the type of the options we are configuring, in this
-case `FlatConfigB`. Here, we pattern match on the barbie-type, and then use the `Applicative`
-instance of `Identity` to get back an `Identity FlatConfig`.
+`execOpt` returns an `Identity x` where `x` is the type of the options we are
+configuring, in this case `FlatConfigB`. Here, we pattern match on the
+barbie-type, and then use the `Applicative` instance of `Identity` to get back
+an `Identity FlatConfig`.
 
 This is still a bit boilerplate-y. Let's look at another way.
 
 ### 2. Using a product type
 
-Looking at `FlatConfigB`, it's only used because of it's `barbie`-like capabilities. Other than that
-it's just a simple product type with the additional `f` before all its sub-types.
+Looking at `FlatConfigB`, it's only used because of it's `barbie`-like
+capabilities. Other than that it's just a simple product type with the
+additional `f` before all its sub-types.
 
-`harg` defines a type almost similar to `Product` (from `Data.Functor.Product`), which works in a
-similar fashion as servant's `:<|>` type. This type is defined in `Options.Harg.Het.Prod` and is
-called `:*` (the `*` stands for product). This type stores barbie-like types and also keeps the `f`
-handy: `data (a :* b) f = a f :* b f`. This is also easily made an instance of `Generic`,
-`FunctorB`, `TraversableB` and `ProductB`. With all that, let's rewrite the options value and the
-function to get the configuration:
+`harg` defines a type almost similar to `Product` (from `Data.Functor.Product`),
+which works in a similar fashion as servant's `:<|>` type. This type is defined
+in `Options.Harg.Het.Prod` and is called `:*` (the `*` stands for product). This
+type stores barbie-like types and also keeps the `f` handy: `data (a :* b) f = a
+f :* b f`. This is also easily made an instance of `Generic`, `FunctorB`,
+`TraversableB` and `ProductB`. With all that, let's rewrite the options value
+and the function to get the configuration:
 
 ``` haskell
-flatConfigOpt2 :: (Single String :* Single Int :* Single String :* Single Bool) Opt
 flatConfigOpt2
+  :: (Single String :* Single Int :* Single String :* Single Bool) Opt
+flatConfigOpt2
   = single dbHostOpt :* single dbPortOpt :* single dirOpt :* single logOpt
 
 getFlatConfig2 :: IO ()
 getFlatConfig2 = do
   host :* port :* dir :* log <- execOptDef flatConfigOpt2
-  print $ runIdentity
-    (FlatConfig <$> getSingle host <*> getSingle port <*> getSingle dir <*> getSingle log)
+  print $ runIdentity $
+    FlatConfig
+    <$> getSingle host
+    <*> getSingle port
+    <*> getSingle dir
+    <*> getSingle log
 ```
 
-This looks aufully similar to the previous version, but without having to write another datatype and
-derive all the instances. `:*` is both a type-level constructor and a value-level function that acts
-like list's `:`. It is also right-associative, so for example `a :* b :* c` is the same as
-`a :* (b :* c)`.
+This looks aufully similar to the previous version, but without having to write
+another datatype and derive all the instances. `:*` is both a type-level
+constructor and a value-level function that acts like list's `:`. It is also
+right-associative, so for example `a :* b :* c` is the same as `a :* (b :* c)`.
 
-The `Single` type constructor is used when talking about a single value, rather than a nested
-datatype. `Single a f` is a simple newtype over `f a`. The reason for using that is simply to switch
-the order of application, so that we can later apply the `f` (here `Opt`) to the compound type
-(`:*`). This makes type definitions look more similar to datatype definitions:
+The `Single` type constructor is used when talking about a single value, rather
+than a nested datatype. `Single a f` is a simple newtype over `f a`. The reason
+for using that is simply to switch the order of application, so that we can
+later apply the `f` (here `Opt`) to the compound type (`:*`). This makes type
+definitions look more similar to datatype definitions:
 
 ``` haskell
 type FlatConfigOpt2
@@ -242,10 +264,12 @@
   :* Single Bool
 ```
 
-In addition, `single` is used to wrap an `f a` into a `Single a f`, and `getSingle` is used
-to unwrap it. Later on we'll see how to construct nested configurations using `Nested`.
+In addition, `single` is used to wrap an `f a` into a `Single a f`, and
+`getSingle` is used to unwrap it. Later on we'll see how to construct nested
+configurations using `Nested`.
 
-However, the real value when having flat datatypes comes from the ability to use `higgledy`.
+However, the real value when having flat datatypes comes from the ability to use
+`higgledy`.
 
 ### 3. Using `HKD` from `higgledy`
 
@@ -260,14 +284,16 @@
   print $ runIdentity (construct result)
 ```
 
-This is the most straightforward way to work with flat configuration types. The `build` function
-takes as arguments the options (`Opt a` where `a` is each type in `FlatConfig`) **in the order they
-appear in the datatype**, and returns the generic representation of a type that's exactly the same
-as `FlatConfigB`. This means that we get all the `barbie` instances for free.
+This is the most straightforward way to work with flat configuration types. The
+`build` function takes as arguments the options (`Opt a` where `a` is each type
+in `FlatConfig`) **in the order they appear in the datatype**, and returns the
+generic representation of a type that's exactly the same as `FlatConfigB`. This
+means that we get all the `barbie` instances for free.
 
-To go back from the `HKD` representation of a datatype to the base one, we use `construct`.
-`construct` uses the applicative instance of the `f` which wraps each type in `FlatConfig` to give
-back an `f FlatConfig` (in our case an `Identity FlatConfig`).
+To go back from the `HKD` representation of a datatype to the base one, we use
+`construct`. `construct` uses the applicative instance of the `f` which wraps
+each type in `FlatConfig` to give back an `f FlatConfig` (in our case an
+`Identity FlatConfig`).
 
 ## Nested datatypes
 
@@ -343,8 +369,9 @@
   deriving (Generic, B.FunctorB, B.TraversableB, B.ProductB)
 ```
 
-To define the option parser, we need option parsers for every type inside it. This was true for
-flat configs too, but we have to manually construct a `DbConfigB Opt` and `ServiceConfigB Opt`:
+To define the option parser, we need option parsers for every type inside it.
+This was true for flat configs too, but we have to manually construct a
+`DbConfigB Opt` and `ServiceConfigB Opt`:
 
 ``` haskell
 configOpt1 :: ConfigB Opt
@@ -365,18 +392,24 @@
 ``` haskell
 getConfig1 :: IO ()
 getConfig1 = do
-  ConfigB (DbConfigB dbHost dbPort) (ServiceConfigB port log) dir <- execOptDef configOpt1
+  ConfigB (DbConfigB dbHost dbPort) (ServiceConfigB port log) dir <-
+    execOptDef configOpt1
   let
     db      = DbConfig <$> dbHost <*> dbPort
     service = ServiceConfig <$> port <*> log
-  print $ runIdentity (Config <$> db <*> service <*> dir)
+  print $ runIdentity $
+    Config
+    <$> db
+    <*> service
+    <*> dir
 ```
 
 ### 2. Using `higgledy`
 
-`higgledy` puts an `f` before every type, so doing something like `HKD Config f` doesn't make sense:
-looking at `ConfigB` it seems like the `f` needs to go to the right hand side of the nested types.
-We can, however, avoid the boilerplate of defining `barbie` types for the nested datatypes:
+`higgledy` puts an `f` before every type, so doing something like `HKD Config f`
+doesn't make sense: looking at `ConfigB` it seems like the `f` needs to go to
+the right hand side of the nested types. We can, however, avoid the boilerplate
+of defining `barbie` types for the nested datatypes:
 
 ``` haskell
 data ConfigH f
@@ -406,14 +439,19 @@
 getConfig2 :: IO ()
 getConfig2 = do
   ConfigH db service dir <- execOptDef configOpt2
-  print $ runIdentity (Config <$> construct db <*> construct service <*> dir)
+  print $ runIdentity $
+    Config
+    <$> construct db
+    <*> construct service
+    <*> dir
 ```
 
 ### 2. Using products
 
-Recall from previously that there's the `Single` type which in general turns `f b` into `b f`. This
-means that, by using `Single` for the directory option, all `f`s are after their types, so we can
-just use `:*` instead of having to declare a new datatype:
+Recall from previously that there's the `Single` type which in general turns `f
+b` into `b f`. This means that, by using `Single` for the directory option, all
+`f`s are after their types, so we can just use `:*` instead of having to declare
+a new datatype:
 
 ``` haskell
 type ConfigP
@@ -428,11 +466,16 @@
 getConfig3 :: IO ()
 getConfig3 = do
   db :* service :* dir <- execOptDef configOpt3
-  print $ runIdentity (Config <$> construct db <*> construct service <*> getSingle dir)
+  print $ runIdentity $
+    Config
+    <$> construct db
+    <*> construct service
+    <*> getSingle dir
 ```
 
-And, to make things look more orthogonal, `harg` defines a type called `Nested`, which is exactly
-the same as `HKD`. There are functions that correspond to `build` and `construct`, too:
+And, to make things look more orthogonal, `harg` defines a type called `Nested`,
+which is exactly the same as `HKD`. There are functions that correspond to
+`build` and `construct`, too:
 
 ```
 Nested    <-> HKD
@@ -460,7 +503,11 @@
 getConfig4 :: IO ()
 getConfig4 = do
   db :* service :* dir <- execOptDef configOpt4
-  print $ runIdentity (Config <$> getNested db <*> getNested service <*> getSingle dir)
+  print $ runIdentity $
+    Config
+    <$> getNested db
+    <*> getNested service
+    <*> getSingle dir
 ```
 
 Pretty cool.
@@ -470,12 +517,13 @@
 `harg` also supports (somewhat limited) subcommands, again by using `optparse-applicative`
 underneath.
 
-Because of limitations with higher kinded data when it comes to sum types, `harg` uses a different
-way to define subcommands. `optparse-applicative` allows defining subcommands that result to the
-same type, which means the user needs to define a sum type, and each subcommand results in a
-different constructor. In contrast, `harg` defines subcommands that can return completely different
-types. Instead of the result being a sum type, where the user has to pattern match on constructors,
-the result is a `Variant`, which is defined (almost) like this:
+Because of limitations with higher kinded data when it comes to sum types,
+`harg` uses a different way to define subcommands. `optparse-applicative` allows
+defining subcommands that result to the same type, which means the user needs to
+define a sum type, and each subcommand results in a different constructor. In
+contrast, `harg` defines subcommands that can return completely different types.
+Instead of the result being a sum type, where the user has to pattern match on
+constructors, the result is a `Variant`, which is defined (almost) like this:
 
 ``` haskell
 data Variant (xs :: [Type]) where
@@ -483,10 +531,12 @@
   There :: Variant xs -> Variant (y ': xs)
 ```
 
-`Variant` is like a sum type which holds all the summands in a type-level list. Instead of pattern
-matching in `Left` or `Right` like when using `Either`, we pattern match on `Here x`, `There (Here x)`
-etc. For a pretty thorough introduction to `Variant` and more heterogeneous types, check out
-[this repo](https://github.com/i-am-tom/learn-me-a-haskell) by [i-am-tom](https://github.com/i-am-tom).
+`Variant` is like a sum type which holds all the summands in a type-level list.
+Instead of pattern matching in `Left` or `Right` like when using `Either`, we
+pattern match on `Here x`, `There (Here x)` etc. For a pretty thorough
+introduction to `Variant` and more heterogeneous types, check out
+[this repo](https://github.com/i-am-tom/learn-me-a-haskell) by
+[i-am-tom](https://github.com/i-am-tom).
 
 ``` haskell
 x :: Variant '[Int, Bool, Char]
@@ -509,10 +559,11 @@
 
 to hold a type-level list of `barbie` types and the `f` to wrap every type with.
 
-To define a type to be used in a subcommand parser we need the target type and the subcommand name,
-which is encoded as a type-level string `Symbol`. There's a handy way to define this. Suppose that
-the the `Config` type above is the configuration type when the command is `app` and another type,
-e.g.`TestConfig` is the configuration when the command is `test`:
+To define a type to be used in a subcommand parser we need the target type and
+the subcommand name, which is encoded as a type-level string `Symbol`. There's a
+handy way to define this. Suppose that the the `Config` type above is the
+configuration type when the command is `app` and another type, e.g.`TestConfig`
+is the configuration when the command is `test`:
 
 ``` haskell
 data TestConfig
@@ -562,8 +613,8 @@
   = configOpt4 :+ testConfigOpt :+ ANil
 ```
 
-The `ANil` here marks the end of the association list (which is a heterogeneous list that associates
-symbols with types).
+The `ANil` here marks the end of the association list (which is a heterogeneous
+list that associates symbols with types).
 
 Here's how to run this parser:
 
@@ -573,11 +624,16 @@
   result <- execCommandsDef subcommandOpt
   case result of
     HereF (db :* service :* dir)
-      -> print $ runIdentity
-       $ Config <$> getNested db <*> getNested service <*> getSingle dir
+      -> print $ runIdentity $
+           Config
+           <$> getNested db
+           <*> getNested service
+           <*> getSingle dir
     ThereF (HereF (foo :* bar))
-      -> print $ runIdentity
-       $ TestConfig <$> getSingle foo <*> getSingle bar
+      -> print $ runIdentity $
+           TestConfig
+           <$> getSingle foo
+           <*> getSingle bar
 ```
 
 Or use `fromVariantF`, which is similar to the `either` function:
@@ -588,12 +644,17 @@
   result <- execCommandsDef subcommandOpt
   fromVariantF result
     (\(db :* service :* dir)
-       -> print $ runIdentity
-       $ Config <$> getNested db <*> getNested service <*> getSingle dir
+       -> print $ runIdentity $
+            Config
+            <$> getNested db
+            <*> getNested service
+            <*> getSingle dir
     )
     (\(foo :* bar)
-       -> print $ runIdentity
-       $ TestConfig <$> getSingle foo <*> getSingle bar
+       -> print $ runIdentity $
+            TestConfig
+            <$> getSingle foo
+            <*> getSingle bar
     )
 ```
 
@@ -609,17 +670,18 @@
   -> r
 ```
 
-The signature will accept the appropriate number of functions depending on the length of the type
-level list.
+The signature will accept the appropriate number of functions depending on the
+length of the type level list.
 
 ## More than just environment variables
 
-You may have noticed the use of `execOptDef` and `execCommandsDef` in all of the examples up to now.
-There are actually more configurable versions of these, called `execOpt` and `execCommands`
-respectively. With these functions the user can select where to get options from. For example,
-`execOptDef` is a shorthand for `execOpt EnvSource`, which means that options will be fetched from
-environment variables only (along with the command line, which is always required, and defaults,
-which can be optionally provided by the user).
+You may have noticed the use of `execOptDef` and `execCommandsDef` in all of the
+examples up to now. There are actually more configurable versions of these,
+called `execOpt` and `execCommands` respectively. With these functions the user
+can select where to get options from. For example, `execOptDef` is a shorthand
+for `execOpt EnvSource`, which means that options will be fetched from
+environment variables only (along with the command line, which is always
+required, and defaults, which can be optionally provided by the user).
 
 The sources currently supported are environment variables, json and yaml files.
 
@@ -674,25 +736,25 @@
   = build @FlatConfig dbHostOpt dbPortOpt dirOpt logOpt
 ```
 
-To use the JSON source, a `FromJSON` instance is required. Thankfully that's easy, since
-`FlatConfig` has `Generic` instance:
+To use the JSON source, a `FromJSON` instance is required. Thankfully that's
+easy, since `FlatConfig` has `Generic` instance:
 
 ``` haskell
 instance FromJSON FlatConfig
 ```
 
-In `harg`, sources are defined as products (using `:*`) of options, which means that the definition
-of the sources is not very different than defining options! If we only needed the environment
-variable source, the options would be:
+In `harg`, sources are defined as products (using `:*`) of options, which means
+that the definition of the sources is not very different than defining options!
+If we only needed the environment variable source, the options would be:
 
 ``` haskell ignore
 envSource :: EnvSource Opt
 envSource = EnvSource
 ```
 
-There's no need to actually define an option for the environment because there's no meaningful
-configuration for this. To use the `EnvSource` along with a json config, we use the following
-option:
+There's no need to actually define an option for the environment because there's
+no meaningful configuration for this. To use the `EnvSource` along with a json
+config, we use the following option:
 
 ``` haskell
 sourceOpt :: (EnvSource :* JSONSource) Opt
@@ -708,8 +770,8 @@
           )
 ```
 
-Here, the type of the option for the JSON source is `ConfigFile`. This type is a wrapper around
-`FilePath`, which looks like this:
+Here, the type of the option for the JSON source is `ConfigFile`. This type is a
+wrapper around `FilePath`, which looks like this:
 
 ``` haskell ignore
 data ConfigFile
@@ -717,8 +779,8 @@
   | NoConfigFile
 ```
 
-This has the advantage that, if the user wants to specify an optional configuration file, they can
-simply say:
+This has the advantage that, if the user wants to specify an optional
+configuration file, they can simply say:
 
 ``` haskell
 jsonOpt :: Opt ConfigFile
@@ -732,17 +794,16 @@
 Also, because `ConfigFile` has an `IsString` instance, there's no need to say
 `long (ConfigFile "json")` (if `OverloadedStrings` is enabled).
 
-There's a bit of a disconnect between `ConfigFile` and the ability to make optional options using
-`Maybe` and `optional`. The reason for it is that the type that `JSONSource` wraps is not
-polymorphic, since it needs to be a filepath specifically.
+There's a bit of a disconnect between `ConfigFile` and the ability to make
+optional options using `Maybe` and `optional`. The reason for it is that the
+type that `JSONSource` wraps is not polymorphic, since it needs to be a filepath
+specifically.
 
 # Roadmap
 
 - Better errors using `optparse-applicative`'s internals
 - Allow user to pass `optparse-applicative` preferences
 - Write tests
-- ~~Be able to provide and get back the same type for multiple subcommands~~
-- ~~Integrate config files (e.g. JSON using aeson)~~
 
 # Credits
 
diff --git a/harg.cabal b/harg.cabal
--- a/harg.cabal
+++ b/harg.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 
 name:           harg
-version:        0.4.0.0
+version:        0.4.1.0
 synopsis:       Haskell program configuration using higher kinded data
 description:    Please see the README on GitHub at <https://github.com/alexpeits/harg#readme>
 homepage:       https://github.com/alexpeits/harg
diff --git a/src/Options/Harg.hs b/src/Options/Harg.hs
--- a/src/Options/Harg.hs
+++ b/src/Options/Harg.hs
@@ -81,6 +81,7 @@
   , B.FunctorB
   , B.TraversableB
   , B.ProductB
+  , B.Rec (..)
 
   -- *** higgledy
   , HKD.HKD
diff --git a/src/Options/Harg/Cmdline.hs b/src/Options/Harg/Cmdline.hs
--- a/src/Options/Harg/Cmdline.hs
+++ b/src/Options/Harg/Cmdline.hs
@@ -78,9 +78,7 @@
           Optparse.flag def active modifiers
   where
     mDef
-      = case getCompose sources of
-          Nothing -> _optDefaultVal
-          Just x  -> Just x
+      = getCompose sources <|> _optDefaultVal
     modifiers
       = foldMap (fromMaybe mempty)
           [ Optparse.long <$> _optLong
diff --git a/src/Options/Harg/Construct.hs b/src/Options/Harg/Construct.hs
--- a/src/Options/Harg/Construct.hs
+++ b/src/Options/Harg/Construct.hs
@@ -344,8 +344,7 @@
 -- with the default 'Left' value @unable to parse: \<input\>@.
 parseWith
   :: (String -> Maybe a)  -- ^ Original parser
-  -> String  -- ^ Input
-  -> Either String a
+  -> (String -> Either String a)
 parseWith parser s
   = maybe (Left err) Right (parser s)
   where
diff --git a/src/Options/Harg/Operations.hs b/src/Options/Harg/Operations.hs
--- a/src/Options/Harg/Operations.hs
+++ b/src/Options/Harg/Operations.hs
@@ -17,14 +17,14 @@
 import           Options.Harg.Het.HList          (AssocListF, MapAssocList(..))
 import           Options.Harg.Het.Prod           ((:*)(..))
 import           Options.Harg.Het.Variant        (VariantF)
-import           Options.Harg.Pretty             (ppOptErrors)
+import           Options.Harg.Pretty             (ppSourceRunErrors)
 import           Options.Harg.Sources            ( accumSourceResults
                                                  , DefaultSources, defaultSources
                                                  , HiddenSources, hiddenSources
                                                  )
-import           Options.Harg.Sources.Types      (GetSource(..), RunSource(..))
+import           Options.Harg.Sources.Types      (GetSource(..), RunSource(..), SourceRunError)
 import           Options.Harg.Subcommands        (Subcommands(..))
-import           Options.Harg.Types              (HargCtx(..), getCtx, Opt, OptError)
+import           Options.Harg.Types              (HargCtx(..), getCtx, Opt)
 import           Options.Harg.Util               (toDummyOpts, allToDummyOpts, compose)
 
 -- | Run the option parser and combine with values from the specified sources,
@@ -209,7 +209,7 @@
 
 failParser
   :: Optparse.Parser a
-  -> [OptError]
+  -> [SourceRunError]
   -> IO a
 failParser parser errs
   = Optparse.handleParseResult (Optparse.Failure failure)
@@ -223,7 +223,7 @@
     parserInfo
       = Optparse.info (Optparse.helper <*> parser) Optparse.forwardOptions
     errStr
-      = ppOptErrors errs
+      = ppSourceRunErrors errs
 
 -- | Run the optparse-applicative parser and return the
 -- 'Optparse.ParserResult'
diff --git a/src/Options/Harg/Pretty.hs b/src/Options/Harg/Pretty.hs
--- a/src/Options/Harg/Pretty.hs
+++ b/src/Options/Harg/Pretty.hs
@@ -1,8 +1,10 @@
 module Options.Harg.Pretty where
 
-import Data.List          (intercalate, nubBy)
-import Data.Maybe         (fromMaybe)
+import Control.Applicative        ((<|>))
+import Data.List                  (intercalate)
+import Data.Maybe                 (fromMaybe)
 
+import Options.Harg.Sources.Types
 import Options.Harg.Types
 
 
@@ -12,31 +14,38 @@
 ppHelp Opt{..}
   = (<> ppEnvVar _optEnvVar) <$> _optHelp
 
-ppOptErrors
-  :: [OptError]
+ppSourceRunErrors
+  :: [SourceRunError]
   -> String
-ppOptErrors
+ppSourceRunErrors
   = intercalate "\n\n"
-  . map ppOptError
-  . nubBy cmpOptErr
+  . map ppSourceRunError
   where
-    cmpOptErr (OptError (SomeOpt l) sl dl) (OptError (SomeOpt r) sr dr)
-      =  _optLong l == _optLong r && sl == sr && dl == dr
-    ppOptError :: OptError -> String
-    ppOptError (OptError (SomeOpt opt) src desc)
+    ppSourceRunError :: SourceRunError -> String
+    ppSourceRunError (SourceRunError Nothing src desc)
+      =  "error: "
+      <> desc
+      <> "\n\t"
+      <> ppSource src
+
+    ppSourceRunError (SourceRunError (Just (SomeOpt opt)) src desc)
       =  "option "
-      <> fromMaybe "<no opt name>" (_optLong opt)
+      <> optId opt
       <> ": "
       <> desc
       <> "\n\t"
       <> ppSource src
       <> ppEnvVar (_optEnvVar opt)
 
+    optId Opt{..}
+      = fromMaybe "<no name available>"
+        $ _optLong <|> (pure <$> _optShort) <|> _optMetavar
+
 ppSource
-  :: Maybe String
+  :: String
   -> String
-ppSource
-  = maybe "" $ \s -> " (source: " <> s <> ")"
+ppSource s
+  = " (source: " <> s <> ")"
 
 ppEnvVar
   :: Maybe String
diff --git a/src/Options/Harg/Sources.hs b/src/Options/Harg/Sources.hs
--- a/src/Options/Harg/Sources.hs
+++ b/src/Options/Harg/Sources.hs
@@ -1,7 +1,3 @@
-{-# LANGUAGE AllowAmbiguousTypes  #-}
-{-# LANGUAGE PolyKinds            #-}
-{-# LANGUAGE TypeFamilies         #-}
-{-# LANGUAGE UndecidableInstances #-}
 module Options.Harg.Sources where
 
 import           Data.Foldable              (foldr')
@@ -12,7 +8,6 @@
 import           Options.Harg.Sources.DefaultStr
 import           Options.Harg.Sources.Env
 import           Options.Harg.Sources.Types
-import           Options.Harg.Types
 
 
 -- | Accumulate all the successful source results and return them,
@@ -20,26 +15,30 @@
 accumSourceResults
   :: forall a f.
      B.TraversableB a
-  => [a (Compose SourceRunResult f)]
-  -> ([OptError], [a (Compose Maybe f)])
+  => [Either SourceRunError (a (Compose SourceRunResult f))]
+  -> ([SourceRunError], [a (Compose Maybe f)])
 accumSourceResults
   = foldr' accumResult ([], [])
   where
     accumResult
-      :: a (Compose SourceRunResult f)
-      -> ([OptError], [a (Compose Maybe f)])
-      -> ([OptError], [a (Compose Maybe f)])
+      :: Either SourceRunError (a (Compose SourceRunResult f))
+      -> ([SourceRunError], [a (Compose Maybe f)])
+      -> ([SourceRunError], [a (Compose Maybe f)])
     accumResult res (e, a)
-      = case B.btraverse go res of
-          (e', a') -> (e' <> e, a' : a)
+      = case res of
+          Left sre -> (sre : e, a)
+          Right res' ->
+            case B.btraverse go res' of
+              (e', a') -> (e' <> e, a' : a)
     go
       :: Compose SourceRunResult f x
-      -> ([OptError], Compose Maybe f x)
+      -> ([SourceRunError], Compose Maybe f x)
     go x
       = case getCompose x of
-          OptFoundNoParse e -> ([e], Compose Nothing)
-          OptParsed a       -> ([], Compose (Just a))
-          _                 -> ([], Compose Nothing)
+          OptParsed a
+            -> ([], Compose (Just a))
+          OptNotFound
+            -> ([], Compose Nothing)
 
 type HiddenSources = DefaultStrSource
 
diff --git a/src/Options/Harg/Sources/DefaultStr.hs b/src/Options/Harg/Sources/DefaultStr.hs
--- a/src/Options/Harg/Sources/DefaultStr.hs
+++ b/src/Options/Harg/Sources/DefaultStr.hs
@@ -28,30 +28,35 @@
     = pure DefaultStrSourceVal
 
 instance
-    B.FunctorB a => RunSource DefaultStrSourceVal a where
+    ( B.FunctorB a
+    , B.TraversableB a
+    ) => RunSource DefaultStrSourceVal a where
   runSource DefaultStrSourceVal opt
     = [runDefaultStrSource opt]
 
+-- TODO: this looks very similar to EnvSource, perhaps unify
 runDefaultStrSource
   :: forall a f.
      ( B.FunctorB a
+     , B.TraversableB a
      , Applicative f
      )
   => a (Compose Opt f)
-  -> a (Compose SourceRunResult f)
+  -> Either SourceRunError (a (Compose SourceRunResult f))
 runDefaultStrSource
-  = B.bmap go
+  = B.btraverse go
   where
-    go :: Compose Opt f x -> Compose SourceRunResult f x
+    go
+      :: Compose Opt f x
+      -> Either SourceRunError (Compose SourceRunResult f x)
     go (Compose opt@Opt{..})
-      = case _optDefaultStr of
-          Nothing
-            -> Compose $ pure <$> OptNotFound
-          Just str
-            -> Compose $ tryParse str
+      = maybe toNotFound parse _optDefaultStr
       where
-        tryParse
-          = either
-              (OptFoundNoParse . toOptError opt (Just "DefaultStrSource"))
-              OptParsed
-          . _optReader
+        parse
+          = either toErr toParsed . _optReader
+        toNotFound
+          = Right $ Compose $ pure <$> OptNotFound
+        toErr
+          = Left . sourceRunError opt "DefaultStrSource"
+        toParsed
+          = Right . Compose . OptParsed
diff --git a/src/Options/Harg/Sources/Env.hs b/src/Options/Harg/Sources/Env.hs
--- a/src/Options/Harg/Sources/Env.hs
+++ b/src/Options/Harg/Sources/Env.hs
@@ -28,7 +28,9 @@
     = pure (EnvSourceVal _hcEnv)
 
 instance
-    B.FunctorB a => RunSource EnvSourceVal a where
+    ( B.FunctorB a
+    , B.TraversableB a
+    ) => RunSource EnvSourceVal a where
   runSource (EnvSourceVal e) opt
     = [runEnvVarSource e opt]
 
@@ -43,24 +45,26 @@
 runEnvVarSource
   :: forall a f.
      ( B.FunctorB a
+     , B.TraversableB a
      , Applicative f
      )
   => Environment
   -> a (Compose Opt f)
-  -> a (Compose SourceRunResult f)
+  -> Either SourceRunError (a (Compose SourceRunResult f))
 runEnvVarSource env
-  = B.bmap go
+  = B.btraverse go
   where
-    go :: Compose Opt f x -> Compose SourceRunResult f x
+    go
+      :: Compose Opt f x
+      -> Either SourceRunError (Compose SourceRunResult f x)
     go (Compose opt@Opt{..})
-      = case _optEnvVar of
-          Nothing
-            -> Compose $ pure <$> OptNotFound
-          Just envVar
-            -> Compose $ maybe OptNotFound tryParse (lookupEnv env envVar)
+      = maybe toNotFound (parse . lookupEnv env) _optEnvVar
       where
-        tryParse
-          = either
-              (OptFoundNoParse . toOptError opt (Just "EnvSource"))
-              OptParsed
-          . _optReader
+        parse
+          = maybe toNotFound (either toErr toParsed . _optReader)
+        toNotFound
+          = Right $ Compose $ pure <$> OptNotFound
+        toErr
+          = Left . sourceRunError opt "EnvSource"
+        toParsed
+          = Right . Compose . OptParsed
diff --git a/src/Options/Harg/Sources/JSON.hs b/src/Options/Harg/Sources/JSON.hs
--- a/src/Options/Harg/Sources/JSON.hs
+++ b/src/Options/Harg/Sources/JSON.hs
@@ -7,6 +7,7 @@
 import           Data.Functor.Compose       (Compose (..))
 import           Data.Functor.Identity      (Identity(..))
 import           GHC.Generics               (Generic)
+import qualified Data.ByteString.Lazy       as LBS
 
 import qualified Data.Aeson                 as JSON
 import qualified Data.Barbie                as B
@@ -23,19 +24,13 @@
 -- the user has specified @defaultVal NoConfigFile@. It holds the contents of
 -- the JSON file as a 'JSON.Value'.
 data JSONSourceVal
-  = JSONSourceVal JSON.Value
+  = JSONSourceVal LBS.ByteString
   | JSONSourceNotRequired
 
 instance GetSource JSONSource Identity where
   type SourceVal JSONSource = JSONSourceVal
-  getSource _ctx (JSONSource (Identity (ConfigFile path))) = do
-    contents <- readFileLBS path
-    case JSON.eitherDecode contents of
-      Right json
-        -> pure $ JSONSourceVal json
-      Left err
-        -> printErrAndExit
-            $ "Error decoding " <> path <> " to JSON: " <> err
+  getSource _ctx (JSONSource (Identity (ConfigFile path)))
+    = JSONSourceVal <$> readFileLBS path
   getSource _ctx (JSONSource (Identity NoConfigFile))
     = pure JSONSourceNotRequired
 
@@ -54,20 +49,22 @@
      , JSON.FromJSON (a Maybe)
      , Applicative f
      )
-  => JSON.Value
+  => LBS.ByteString
   -> a (Compose Opt f)
-  -> a (Compose SourceRunResult f)
-runJSONSource json opt
+  -> Either SourceRunError (a (Compose SourceRunResult f))
+runJSONSource json _opt
   = case res of
-      JSON.Success v -> B.bmap toSuccess v
-      JSON.Error _e  -> B.bmap toFailure opt
+      Right v  -> Right $ B.bmap toSuccess v
+      Left exc -> Left $ toError exc
   where
-    res :: JSON.Result (a Maybe)
+    res :: Either String (a Maybe)
     res
-      = JSON.fromJSON json
+      = JSON.eitherDecode json
+
     toSuccess :: Maybe x -> Compose SourceRunResult f x
     toSuccess mx
       = Compose $ pure <$> maybe OptNotFound OptParsed mx
-    toFailure :: Compose Opt f x -> Compose SourceRunResult f x
-    toFailure _
-      = Compose $ pure <$> OptNotFound
+
+    toError :: String -> SourceRunError
+    toError
+      = SourceRunError Nothing "JSONSource"
diff --git a/src/Options/Harg/Sources/Types.hs b/src/Options/Harg/Sources/Types.hs
--- a/src/Options/Harg/Sources/Types.hs
+++ b/src/Options/Harg/Sources/Types.hs
@@ -5,7 +5,7 @@
 
 import Data.Functor.Compose  (Compose (..))
 import Data.Kind             (Type)
-import           Data.String (IsString(..))
+import Data.String           (IsString(..))
 
 import Options.Harg.Het.Prod
 import Options.Harg.Types
@@ -14,13 +14,28 @@
 -- | Holds errors that occur when running a source.
 data SourceRunResult a
   = OptNotFound  -- ^ Source doesn't include the option
-  | OptFoundNoParse OptError  -- ^ Option cannot be parsed from source
   | OptParsed a  -- ^ Successful parsing
   deriving Functor
 
--- | This class enables a type that describes a source to fetch
--- the source contents, potentially producing side effects (e.g. reading
--- a file).
+data SourceRunError
+  = SourceRunError
+      { _sreOpt        :: Maybe SomeOpt
+      , _sreSourceName :: String
+      , _sreError      :: String
+      }
+
+-- | Create a 'SourceRunError' by existentially wrapping an option in 'SomeOpt'.
+sourceRunError
+  :: forall a.
+     Opt a
+  -> String
+  -> String
+  -> SourceRunError
+sourceRunError
+  = SourceRunError . Just . SomeOpt
+
+-- | This class enables a type that describes a source to fetch the source
+-- contents, potentially producing side effects (e.g. reading a file).
 class GetSource
     (c :: (Type -> Type) -> Type)
     (f :: (Type -> Type)) where
@@ -45,7 +60,7 @@
     :: Applicative f
     => s
     -> a (Compose Opt f)
-    -> [a (Compose SourceRunResult f)]
+    -> [Either SourceRunError (a (Compose SourceRunResult f))]
 
 instance
     ( RunSource l a
diff --git a/src/Options/Harg/Sources/YAML.hs b/src/Options/Harg/Sources/YAML.hs
--- a/src/Options/Harg/Sources/YAML.hs
+++ b/src/Options/Harg/Sources/YAML.hs
@@ -53,22 +53,20 @@
      )
   => BS.ByteString
   -> a (Compose Opt f)
-  -> a (Compose SourceRunResult f)
-runYAMLSource yaml opt
+  -> Either SourceRunError (a (Compose SourceRunResult f))
+runYAMLSource yaml _opt
   = case res of
-      Right v  -> B.bmap toSuccess v
-      Left exc -> B.bmap (toFailure exc) opt
+      Right v  -> Right $ B.bmap toSuccess v
+      Left exc -> Left $ toError exc
   where
     res :: Either YAML.ParseException (a Maybe)
     res
       = YAML.decodeEither' yaml
+
     toSuccess :: Maybe x -> Compose SourceRunResult f x
     toSuccess mx
       = Compose $ pure <$> maybe OptNotFound OptParsed mx
-    toFailure
-      :: YAML.ParseException
-      -> Compose Opt f x
-      -> Compose SourceRunResult f x
-    toFailure exc (Compose o)
-      = Compose
-        $ OptFoundNoParse (toOptError o (Just "YAMLSource") (displayException exc))
+
+    toError :: YAML.ParseException -> SourceRunError
+    toError exc
+      = SourceRunError Nothing "YAMLSource" (displayException exc)
diff --git a/src/Options/Harg/Subcommands.hs b/src/Options/Harg/Subcommands.hs
--- a/src/Options/Harg/Subcommands.hs
+++ b/src/Options/Harg/Subcommands.hs
@@ -60,7 +60,7 @@
        )
     => s
     -> AssocListF ts xs (Compose Opt f)
-    -> ([OptError], [Optparse.Mod Optparse.CommandFields (VariantF xs f)])
+    -> ([SourceRunError], [Optparse.Mod Optparse.CommandFields (VariantF xs f)])
 
 instance ExplSubcommands Z ts xs '[] => Subcommands ts xs where
   mapSubcommand = explMapSubcommand @Z @ts @xs @'[] SZ
@@ -79,7 +79,7 @@
     => SNat n
     -> s
     -> AssocListF ts xs (Compose Opt f)
-    -> ([OptError], [Optparse.Mod Optparse.CommandFields (VariantF (acc ++ xs) f)])
+    -> ([SourceRunError], [Optparse.Mod Optparse.CommandFields (VariantF (acc ++ xs) f)])
 
 instance ExplSubcommands n '[] '[] acc where
   explMapSubcommand _ _ _ = ([], [])
diff --git a/src/Options/Harg/Types.hs b/src/Options/Harg/Types.hs
--- a/src/Options/Harg/Types.hs
+++ b/src/Options/Harg/Types.hs
@@ -72,17 +72,6 @@
       , _aReader     :: OptReader a
       }
 
--- | Datatype that holds errors that arise when running the sources.
--- The reason why this is the only place where errors occur is that,
--- if something goes wrong when running the parser, it will be handled
--- by @optparse-applicative@.
-data OptError
-  = OptError
-      { _oeOpt    :: SomeOpt       -- ^ Existentially quantified 'Opt'
-      , _oeSource :: Maybe String  -- ^ Source name
-      , _oeDesc   :: String        -- ^ Error description
-      }
-
 -- | Existential wrapper for 'Opt', so that many options can be carried in
 -- a list.
 data SomeOpt where
@@ -119,11 +108,3 @@
 pureCtx :: Environment -> Args -> HargCtx
 pureCtx
   = HargCtx
-
-toOptError
-  :: Opt a
-  -> Maybe String
-  -> String
-  -> OptError
-toOptError
-  = OptError . SomeOpt
