diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# Floskell 0.10.6 (2021-12-14)
+
+* Add support for building with GHC-9.0.1, GHC-9.2.1
+* Fix formatting of package-qualified imports
+* Avoid inserting blank lines between comments and declarations
+
 # Floskell 0.10.5 (2020-09-21)
 
 * Fix indentation of nested list and tuple expressions
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -18,29 +18,29 @@
 
 ## Installation
 
-    $ git clone https://github.com/ennocramer/floskell
-    $ cd floskell
-    $ stack install
+    git clone https://github.com/ennocramer/floskell
+    cd floskell
+    stack install
 
 
 ## Usage
 
 Floskell can be used to reformat Haskell source files in place
 
-    $ floskell path/to/sourcefile.hs
+    floskell path/to/sourcefile.hs
 
 or as a pipeline processor
 
-    $ cat path/to/sourcefile.hs | floskell > outfile.hs
+    cat path/to/sourcefile.hs | floskell > outfile.hs
 
 One of the predefined formatting styles can be selected with the
 `--style` option
 
-    $ floskell --style cramer path/to/sourcefile.hs
+    floskell --style cramer path/to/sourcefile.hs
 
 Or the style can be read from a configuration file
 
-    $ floskell --config path/to/config.json path/to/sourcefile.hs
+    floskell --config path/to/config.json path/to/sourcefile.hs
 
 If neither style nor configuration file is given on the command line,
 Floskell will try to find a configuration file in the current working
@@ -238,7 +238,7 @@
 The `--print-config` command line option can be used to create an
 initial configuration file.
 
-    $ floskell --style cramer --print-config > ~/.floskell.json
+    floskell --style cramer --print-config > ~/.floskell.json
 
 This command will create a configuration file with all fields and the
 entire definition of the selected style in the `formatting` block.
diff --git a/TEST.md b/TEST.md
--- a/TEST.md
+++ b/TEST.md
@@ -156,6 +156,7 @@
 import qualified Data.ByteString (ByteString,pack,unpack)
 import qualified Data.ByteString as BS (pack, unpack)
 import Control.Monad hiding (forM)
+import {-# SOURCE #-} safe qualified "foo" Foo as F
 ```
 
 ## Decl
@@ -860,6 +861,14 @@
   where
     {-# INLINE_LATE step1 #-}
     step1 _ _   = undefined
+```
+
+Comments between declarations do not cause empty lines.
+
+``` haskell
+f :: ()
+--
+f = ()
 ```
 
 ## Indentation and Line Prefixes
diff --git a/floskell.cabal b/floskell.cabal
--- a/floskell.cabal
+++ b/floskell.cabal
@@ -1,6 +1,6 @@
 cabal-version:      >=1.10
 name:               floskell
-version:            0.10.5
+version:            0.10.6
 license:            BSD3
 license-file:       LICENSE.md
 copyright:
@@ -31,6 +31,7 @@
     BENCHMARK.md
     TEST.md
     stack.yaml
+    styles/*.md
 
 source-repository head
     type:     git
@@ -55,10 +56,10 @@
     default-language: Haskell2010
     ghc-options:      -Wall
     build-depends:
-        base >=4.9 && <4.15,
-        aeson >=0.11.3.0 && <1.6,
-        attoparsec >=0.13.1.0 && <0.14,
-        bytestring >=0.10.8.1 && <0.11,
+        base >=4.9 && <4.17,
+        aeson >=0.11.3.0 && <2.1,
+        attoparsec >=0.13.1.0 && <0.15,
+        bytestring >=0.10.8.1 && <0.12,
         containers >=0.5.7.1 && <0.7,
         data-default >=0.7.1.1 && <0.8,
         directory >=1.2.6.2 && <1.4,
@@ -79,12 +80,12 @@
         -Wall -Wno-missing-home-modules -optP-Wno-nonportable-include-path
 
     build-depends:
-        base >=4.9 && <4.15,
+        base >=4.9 && <4.17,
         floskell -any,
         aeson-pretty >=0.8.2 && <0.9,
-        bytestring >=0.10.8.1 && <0.11,
+        bytestring >=0.10.8.1 && <0.12,
         directory >=1.2.6.2 && <1.4,
-        ghc-prim >=0.5.0.0 && <0.7,
+        ghc-prim >=0.5.0.0 && <0.9,
         haskell-src-exts >=1.19 && <1.24,
         optparse-applicative >=0.12.1.0 && <0.17,
         text >=1.2.2.2 && <1.3
@@ -97,9 +98,9 @@
     default-language: Haskell2010
     ghc-options:      -Wall -threaded -rtsopts -with-rtsopts=-N
     build-depends:
-        base >=4.9 && <4.15,
+        base >=4.9 && <4.17,
         floskell -any,
-        bytestring >=0.10.8.1 && <0.11,
+        bytestring >=0.10.8.1 && <0.12,
         deepseq >=1.4.2.0 && <1.5,
         exceptions >=0.8.3 && <0.12,
         haskell-src-exts >=1.19 && <1.24,
@@ -115,13 +116,13 @@
     default-language: Haskell2010
     ghc-options:      -Wall -threaded -rtsopts -with-rtsopts=-N
     build-depends:
-        base >=4.9 && <4.15,
+        base >=4.9 && <4.17,
         floskell -any,
-        bytestring >=0.10.8.1 && <0.11,
+        bytestring >=0.10.8.1 && <0.12,
         criterion >=1.1.1.0 && <1.6,
         deepseq >=1.4.2.0 && <1.5,
         exceptions >=0.8.3 && <0.11,
-        ghc-prim >=0.5.0.0 && <0.7,
+        ghc-prim >=0.5.0.0 && <0.9,
         haskell-src-exts >=1.19 && <1.24,
         text >=1.2.2.2 && <1.3,
         utf8-string >=1.0.1.1 && <1.1
diff --git a/src/Floskell/Config.hs b/src/Floskell/Config.hs
--- a/src/Floskell/Config.hs
+++ b/src/Floskell/Config.hs
@@ -221,26 +221,28 @@
     deriving ( Eq, Ord, Generic )
 
 data OptionConfig =
-    OptionConfig { cfgOptionSortPragmas           :: !Bool
-                 , cfgOptionSplitLanguagePragmas  :: !Bool
-                 , cfgOptionSortImports           :: !SortImportsRule
-                 , cfgOptionSortImportLists       :: !Bool
-                 , cfgOptionAlignSumTypeDecl      :: !Bool
-                 , cfgOptionFlexibleOneline       :: !Bool
-                 , cfgOptionPreserveVerticalSpace :: !Bool
-                 , cfgOptionDeclNoBlankLines      :: !(Set DeclarationConstruct)
+    OptionConfig { cfgOptionSortPragmas            :: !Bool
+                 , cfgOptionSplitLanguagePragmas   :: !Bool
+                 , cfgOptionSortImports            :: !SortImportsRule
+                 , cfgOptionSortImportLists        :: !Bool
+                 , cfgOptionAlignSumTypeDecl       :: !Bool
+                 , cfgOptionFlexibleOneline        :: !Bool
+                 , cfgOptionPreserveVerticalSpace  :: !Bool
+                 , cfgOptionDeclNoBlankLines       :: !(Set DeclarationConstruct)
+                 , cfgOptionAlignLetBindsAndInExpr :: !Bool
                  }
     deriving ( Generic )
 
 instance Default OptionConfig where
-    def = OptionConfig { cfgOptionSortPragmas           = False
-                       , cfgOptionSplitLanguagePragmas  = False
-                       , cfgOptionSortImports           = NoImportSort
-                       , cfgOptionSortImportLists       = False
-                       , cfgOptionAlignSumTypeDecl      = False
-                       , cfgOptionFlexibleOneline       = False
-                       , cfgOptionPreserveVerticalSpace = False
-                       , cfgOptionDeclNoBlankLines      = Set.empty
+    def = OptionConfig { cfgOptionSortPragmas            = False
+                       , cfgOptionSplitLanguagePragmas   = False
+                       , cfgOptionSortImports            = NoImportSort
+                       , cfgOptionSortImportLists        = False
+                       , cfgOptionAlignSumTypeDecl       = False
+                       , cfgOptionFlexibleOneline        = False
+                       , cfgOptionPreserveVerticalSpace  = False
+                       , cfgOptionDeclNoBlankLines       = Set.empty
+                       , cfgOptionAlignLetBindsAndInExpr = False
                        }
 
 data Config = Config { cfgPenalty :: !PenaltyConfig
diff --git a/src/Floskell/ConfigFile.hs b/src/Floskell/ConfigFile.hs
--- a/src/Floskell/ConfigFile.hs
+++ b/src/Floskell/ConfigFile.hs
@@ -1,6 +1,8 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE CPP #-}
 
 module Floskell.ConfigFile
     ( AppConfig(..)
@@ -27,12 +29,21 @@
 import           Data.Aeson
                  ( (.:?), (.=), FromJSON(..), ToJSON(..) )
 import qualified Data.Aeson                 as JSON
-import qualified Data.Aeson.Parser          as JSON ( json' )
 import qualified Data.Aeson.Types           as JSON ( typeMismatch )
+#if MIN_VERSION_aeson(2,0,0)
+import qualified Data.Aeson.KeyMap          as JSON ( unionWith )
+#endif
 import qualified Data.Attoparsec.ByteString as AP
 import qualified Data.ByteString            as BS
 import           Data.Char                  ( isLetter, isSpace )
-import qualified Data.HashMap.Lazy          as HashMap
+
+#if MIN_VERSION_aeson(2,0,0)
+import qualified Data.Aeson.KeyMap          as Map
+#else
+import qualified Data.Aeson.Parser          as JSON ( json' )
+import qualified Data.HashMap.Lazy          as Map
+#endif
+
 import           Data.List                  ( inits )
 import qualified Data.Text                  as T
 
@@ -90,7 +101,7 @@
         mergeJSON JSON.Null r = r
         mergeJSON l JSON.Null = l
         mergeJSON (JSON.Object l) (JSON.Object r) =
-            JSON.Object (HashMap.unionWith mergeJSON l r)
+            JSON.Object (Map.unionWith mergeJSON l r)
         mergeJSON _ r = r
 
     parseJSON v = JSON.typeMismatch "AppConfig" v
diff --git a/src/Floskell/Pretty.hs b/src/Floskell/Pretty.hs
--- a/src/Floskell/Pretty.hs
+++ b/src/Floskell/Pretty.hs
@@ -392,12 +392,12 @@
     go (col - correction) xs
   where
     go _ [] = return ()
-    go col [x'] = do
+    go col [ x' ] = do
         printComments Before x'
         column col $ operator ctx sep
         prettyPrint x'
         printComments After x'
-    go col (x':xs') = do
+    go col (x' : xs') = do
         printComments Before x'
         cut $ do
             column col $ operator ctx sep
@@ -512,14 +512,6 @@
   where
     prettyGroups = inter blankline . map (inter newline . map (cut . pretty))
 
-skipBlank :: Annotated ast
-          => (ast NodeInfo -> ast NodeInfo -> Bool)
-          -> ast NodeInfo
-          -> ast NodeInfo
-          -> Bool
-skipBlank skip a b = skip a b && null (filterComments After a)
-    && null (filterComments Before b)
-
 skipBlankAfterDecl :: Decl a -> Bool
 skipBlankAfterDecl a = case a of
     TypeSig{} -> True
@@ -536,17 +528,17 @@
     _ -> False
 
 skipBlankDecl :: Decl NodeInfo -> Decl NodeInfo -> Bool
-skipBlankDecl = skipBlank $ \a _ -> skipBlankAfterDecl a
+skipBlankDecl a _ = skipBlankAfterDecl a
 
 skipBlankClassDecl :: ClassDecl NodeInfo -> ClassDecl NodeInfo -> Bool
-skipBlankClassDecl = skipBlank $ \a _ -> case a of
+skipBlankClassDecl a _ = case a of
     (ClsDecl _ decl) -> skipBlankAfterDecl decl
     ClsTyDef{} -> True
     ClsDefSig{} -> True
     _ -> False
 
 skipBlankInstDecl :: InstDecl NodeInfo -> InstDecl NodeInfo -> Bool
-skipBlankInstDecl = skipBlank $ \a _ -> case a of
+skipBlankInstDecl a _ = case a of
     (InsDecl _ decl) -> skipBlankAfterDecl decl
     _ -> False
 
@@ -767,12 +759,13 @@
 
 instance Pretty ImportDecl where
     prettyPrint ImportDecl{..} = do
-        inter space . map write $
-            filter (not . BS.null)
+        inter space . map string $
+            filter (not . null)
                    [ "import"
                    , if importSrc then "{-# SOURCE #-}" else ""
                    , if importSafe then "safe" else ""
                    , if importQualified then "qualified" else ""
+                   , maybe "" show importPkg
                    ]
         atTabStop stopImportModule
         space
@@ -1618,18 +1611,22 @@
             write "let "
             prettyOnside (CompactBinds binds)
             spaceOrNewline
-            write "in "
+            nl <- gets psNewline
+            alignP <- getOption cfgOptionAlignLetBindsAndInExpr
+            write $ if nl && alignP then "in  " else "in "
             prettyOnside expr
 
-        vertical = withIndentAfter cfgIndentLet
-                                   (do
-                                        write "let"
-                                        withIndent cfgIndentLetBinds $
-                                            pretty (CompactBinds binds))
-                                   (do
-                                        newline
-                                        write "in"
-                                        withIndent cfgIndentLetIn $ pretty expr)
+        vertical = withIndentAfter
+                       cfgIndentLet
+                       (do
+                            write "let"
+                            withIndent cfgIndentLetBinds $
+                                pretty (CompactBinds binds))
+                       (do
+                            newline
+                            alignP <- getOption cfgOptionAlignLetBindsAndInExpr
+                            write $ if alignP then "in " else "in"
+                            withIndent cfgIndentLetIn $ pretty expr)
 
     prettyPrint (If _ expr expr' expr'') = withLayout cfgLayoutIf flex vertical
       where
diff --git a/src/Floskell/Styles.hs b/src/Floskell/Styles.hs
--- a/src/Floskell/Styles.hs
+++ b/src/Floskell/Styles.hs
@@ -79,14 +79,15 @@
 
     groupWsOverrides = []
 
-    cfgOptions = OptionConfig { cfgOptionSortPragmas           = False
-                              , cfgOptionSplitLanguagePragmas  = False
-                              , cfgOptionSortImports           = NoImportSort
-                              , cfgOptionSortImportLists       = False
-                              , cfgOptionAlignSumTypeDecl      = True
-                              , cfgOptionFlexibleOneline       = False
-                              , cfgOptionPreserveVerticalSpace = False
-                              , cfgOptionDeclNoBlankLines      = Set.empty
+    cfgOptions = OptionConfig { cfgOptionSortPragmas            = False
+                              , cfgOptionSplitLanguagePragmas   = False
+                              , cfgOptionSortImports            = NoImportSort
+                              , cfgOptionSortImportLists        = False
+                              , cfgOptionAlignSumTypeDecl       = True
+                              , cfgOptionFlexibleOneline        = False
+                              , cfgOptionPreserveVerticalSpace  = False
+                              , cfgOptionDeclNoBlankLines       = Set.empty
+                              , cfgOptionAlignLetBindsAndInExpr = False
                               }
 
 cramerCfg :: Config
@@ -192,14 +193,15 @@
         ]
 
     cfgOptions =
-        OptionConfig { cfgOptionSortPragmas           = True
-                     , cfgOptionSplitLanguagePragmas  = True
-                     , cfgOptionSortImports           = SortImportsByPrefix
-                     , cfgOptionSortImportLists       = True
-                     , cfgOptionAlignSumTypeDecl      = False
-                     , cfgOptionFlexibleOneline       = False
-                     , cfgOptionPreserveVerticalSpace = True
-                     , cfgOptionDeclNoBlankLines      = Set.empty
+        OptionConfig { cfgOptionSortPragmas            = True
+                     , cfgOptionSplitLanguagePragmas   = True
+                     , cfgOptionSortImports            = SortImportsByPrefix
+                     , cfgOptionSortImportLists        = True
+                     , cfgOptionAlignSumTypeDecl       = False
+                     , cfgOptionFlexibleOneline        = False
+                     , cfgOptionPreserveVerticalSpace  = True
+                     , cfgOptionDeclNoBlankLines       = Set.empty
+                     , cfgOptionAlignLetBindsAndInExpr = False
                      }
 
 gibianskyCfg :: Config
@@ -280,14 +282,15 @@
     groupWsOverrides =
         [ (ConfigMapKey (Just "{") Nothing, Whitespace WsBoth WsAfter False) ]
 
-    cfgOptions = OptionConfig { cfgOptionSortPragmas           = False
-                              , cfgOptionSplitLanguagePragmas  = False
-                              , cfgOptionSortImports           = NoImportSort
-                              , cfgOptionSortImportLists       = False
-                              , cfgOptionAlignSumTypeDecl      = False
-                              , cfgOptionFlexibleOneline       = False
-                              , cfgOptionPreserveVerticalSpace = False
-                              , cfgOptionDeclNoBlankLines      = Set.empty
+    cfgOptions = OptionConfig { cfgOptionSortPragmas            = False
+                              , cfgOptionSplitLanguagePragmas   = False
+                              , cfgOptionSortImports            = NoImportSort
+                              , cfgOptionSortImportLists        = False
+                              , cfgOptionAlignSumTypeDecl       = False
+                              , cfgOptionFlexibleOneline        = False
+                              , cfgOptionPreserveVerticalSpace  = False
+                              , cfgOptionDeclNoBlankLines       = Set.empty
+                              , cfgOptionAlignLetBindsAndInExpr = False
                               }
 
 johanTibellCfg :: Config
@@ -367,14 +370,15 @@
           )
         ]
 
-    cfgOptions = OptionConfig { cfgOptionSortPragmas           = False
-                              , cfgOptionSplitLanguagePragmas  = False
-                              , cfgOptionSortImports           = NoImportSort
-                              , cfgOptionSortImportLists       = False
-                              , cfgOptionAlignSumTypeDecl      = True
-                              , cfgOptionFlexibleOneline       = True
-                              , cfgOptionPreserveVerticalSpace = False
-                              , cfgOptionDeclNoBlankLines      = Set.empty
+    cfgOptions = OptionConfig { cfgOptionSortPragmas            = False
+                              , cfgOptionSplitLanguagePragmas   = False
+                              , cfgOptionSortImports            = NoImportSort
+                              , cfgOptionSortImportLists        = False
+                              , cfgOptionAlignSumTypeDecl       = True
+                              , cfgOptionFlexibleOneline        = True
+                              , cfgOptionPreserveVerticalSpace  = False
+                              , cfgOptionDeclNoBlankLines       = Set.empty
+                              , cfgOptionAlignLetBindsAndInExpr = False
                               }
 
 -- | Base style definition.
diff --git a/src/main/Test.hs b/src/main/Test.hs
--- a/src/main/Test.hs
+++ b/src/main/Test.hs
@@ -10,7 +10,7 @@
 
 import           Data.ByteString.Lazy         ( ByteString )
 import qualified Data.ByteString.Lazy         as L
-import qualified Data.ByteString.Lazy.Builder as B
+import qualified Data.ByteString.Builder      as B ( toLazyByteString )
 import qualified Data.ByteString.Lazy.UTF8    as UTF8
 import           Data.Maybe                   ( mapMaybe )
 import qualified Data.Text                    as T
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,6 +1,5 @@
-resolver: lts-16.3
+resolver: lts-18.18
 packages:
 - '.'
 extra-deps:
-- haskell-src-exts-1.23.1
 - monad-dijkstra-0.1.1.3
diff --git a/styles/base.md b/styles/base.md
new file mode 100644
--- /dev/null
+++ b/styles/base.md
@@ -0,0 +1,961 @@
+# Introduction
+
+This file acts both as a presentation of the Floskell formatting
+styles, as well as a set of regression tests.
+
+You can see how a particular style will format Haskell source by
+reading the matching Markdown file in the styles/ directory.
+
+For regression testing, the canonical source, TEST.md in the root
+directory, is parsed and each Haskell code block formatted according
+to all predefined styles.  The formatted output is then compared with
+the corresponding, already formatted code block in the <style\>.md file
+in the styles/ subdirectory.
+
+The regression test will also verify that repeated invocations of the
+pretty printer will not modify an already formatted piece of code.
+
+The following code block acts as a quick presentation for the
+different formatting styles, by presenting a mixture of common Haskell
+constructs.
+
+``` haskell
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+{- |
+Module: Style.Haskell.Example
+
+Haskell Code Style Example.
+-}
+module Style.Haskell.Example (
+                               -- * Types
+                               Enum(..), Either(..), Point(..)
+                               -- * Functions
+                             , hello ) where
+
+-- Module imports
+import qualified Control.Monad.Trans.State
+    ( State, evalState, execState, get, modify, put, runState )
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import Prelude hiding ( map )
+
+-- Data declarations
+data Enum = CaseA | CaseB | CaseC
+    deriving ( Eq, Enum, Show )
+
+data Either a b = Left a | Right b
+    deriving ( Eq, Show )
+
+data Point = Point { pointX :: Float, pointY :: Float, pointLabel :: String }
+    deriving ( Eq, Show )
+
+-- Type classes
+class Functor f => Applicative a where
+    pure :: b -> a b
+    ap :: a (b -> c) -> a b -> a c
+
+class Fundep a b | a -> b where
+    convert :: a -> b
+
+instance Functor f => Functor (Wrap f) where
+    fmap f (Wrap x) = Wrap $ fmap f x
+
+-- Values
+origin :: Point
+origin = Point { pointX = 0, pointY = 0, pointLabel = "Origin" }
+
+lorem :: [ String ]
+lorem = [ "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+        , "Curabitur nec ante nec mauris ornare suscipit."
+        , "In ac vulputate libero."
+        , "Duis eget magna non purus imperdiet molestie nec quis mauris."
+        , "Praesent blandit quam vel arcu pellentesque, id aliquet turpis faucibus."
+        ]
+
+-- Functions
+facs :: [ Int ]
+facs = [ 1, 1 ] ++ zipWith (+) (tailfacs)
+
+hello :: MonadIO m => m ()
+hello = do
+    name <- liftIO getLine
+    liftIO . putStrLn $ greetings name
+  where
+    greetings n = "Hello " ++ n ++ "!"
+
+letExpr :: Point -> String
+letExp x = let y = 1
+               z = 2 in if x > 0 then y else z
+
+ifExpr :: Bool -> Bool
+ifExpr b = if b == True then False else True
+
+caseExpr :: [ a ] -> Maybe a
+caseExpr xs = case xs of
+    [] -> Nothing
+    (x : _) -> Just x
+
+guarded :: Int -> Int
+guarded x
+    | x == 0 = 1
+    | x == 1 = 1
+    | otherwise = guarded (x - 2) + guarded (x - 1)
+
+someLongFunctionNameWithALotOfParameters :: ( MonadIO m, MonadRandom m )
+    => String -> (String -> String) -> m ()
+someLongFunctionNameWithALotOfParameters = undefined
+```
+
+# Unit Tests
+
+## ModuleHead and ExportSpecList
+
+Without exports
+
+``` haskell
+module Main where
+```
+
+With exports
+
+``` haskell
+module Main ( foo, bar, baz, main ) where
+```
+
+With exports and comments
+
+``` haskell
+module Main (
+              -- * Main Program
+              main
+              -- * Functions
+            , foo -- foo function
+            , bar -- bar function
+            , baz -- baz function
+            ) where
+```
+
+With deprecation
+
+``` haskell
+module Main {-# DEPRECATED "no longer supported" #-} where
+```
+
+With warnings
+
+``` haskell
+module Main {-# WARNING "do not use" #-} where
+```
+
+## ImportDecl
+
+``` haskell
+import Prelude
+import Data.Text ( Text )
+import qualified Data.Text as T
+import qualified Data.ByteString ( ByteString, pack, unpack )
+import qualified Data.ByteString as BS ( pack, unpack )
+import Control.Monad hiding ( forM )
+import {-# SOURCE #-} safe qualified "foo" Foo as F
+```
+
+## Decl
+
+### TypeDecl
+
+``` haskell
+type Name = String
+
+type Pair a = ( a, a )
+
+type Fun a b = a -> b
+```
+
+### DataDecl and GDataDecl
+
+``` haskell
+data Void
+
+data Unit = Unit
+
+data Maybe a = Nothing | Just a
+
+data Num a => SomeNum = SomeNum a
+
+newtype RWS r w s = RWS (ReaderT r (WriterT w (StateT s Identity)))
+    deriving ( Functor, Applicative, Monad )
+
+data Enum = One   -- Foo
+          | Two   -- Bar
+          | Three -- Baz
+
+data Foo
+    deriving ()
+
+data Foo
+    deriving Show
+
+data Foo
+    deriving ( Show )
+
+data Foo
+    deriving ( Eq, Ord )
+
+data Expr :: * -> * where
+    Const :: Int -> Expr Int
+    Plus :: Expr Int -> Expr Int -> Expr Int
+    Eq :: Expr Int -> Expr Int -> Expr Bool
+    deriving ( Show )
+
+data Term a where
+    Lit :: { val :: Int } -> Term Int
+    Succ :: { num :: Term Int } -> Term Int
+    Pred :: { num :: Term Int } -> Term Int
+    IsZero :: { arg :: Term Int } -> Term Bool
+    Pair :: { arg1 :: Term a, arg2 :: Term b } -> Term ( a, b )
+    If :: { cnd :: Term Bool, tru :: Term a, fls :: Term a } -> Term a
+```
+
+### TypeFamDecl, TypeInsDecl, and ClosedTypeFamDecl
+
+``` haskell
+type family Mutable v
+
+type family Mutable v = (r :: *)
+
+type family Mutable v = r | r -> v
+
+type instance Mutable Int = MIntVector
+
+type family Store a where
+    Store Bool = [ Int ]
+    Store a = [ a ]
+
+type family Store a = (r :: *) where
+    Store a = [ a ]
+
+type family Store a = r | r -> a where
+    Store a = [ a ]
+```
+
+### DataFamDecl, DataInsDecl, and GDataInsDecl
+
+``` haskell
+data family List a
+
+data instance List () = NilList Int
+
+data instance List Char = CharNil | CharCons Char (List Char)
+    deriving ( Eq, Ord, Show )
+
+data instance List Int :: * where
+    IntNil :: List Int
+    IntCons :: Int -> List Int
+    deriving ( Eq, Ord, Show )
+
+data instance List Int :: * where
+    IntNil :: List Int
+    IntCons :: { val :: Int } -> List Int
+    deriving ( Eq, Ord, Show )
+
+newtype Penalty = Penalty Int
+    deriving ( Eq, Ord )
+    deriving stock ( Read, Show )
+    deriving newtype ( Num )
+    deriving anyclass ( FromJSON, ToJSON )
+    deriving ( Semigroup, Monoid ) via M.Sum Int
+```
+
+### ClassDecl and InstDecl
+
+``` haskell
+class Monoid a where
+    mempty :: a
+    mappend :: a -> a -> a
+
+class Applicative m => Monad m where
+    fail :: m a
+    return :: a -> m a
+    (>>=) :: a -> (a -> m b) -> m b
+
+class Monad m => MonadState s m | m -> s where
+    get :: m s
+    put :: s -> m ()
+    state :: (s -> ( a, s )) -> m a
+
+class ToJSON a where
+    toJSON :: a -> Value
+    default toJSON :: ( Generic a, GToJSON (Rep a) ) => a -> Value
+    toJSON = genericToJSON defaultOptions
+
+instance ToJSON ()
+
+instance Bounded Bool where
+    minBound = False
+
+    maxBound = True
+
+instance Semigroup a => Monoid (Maybe a) where
+    mempty = Nothing
+
+    Nothing `mappend` m = m
+    m `mappend` Nothing = m
+    Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
+
+instance Data () where
+    type Base = ()
+
+    newtype Wrapped = Wrapped { unWrap :: () }
+
+    data Expr :: * -> * where
+        Const :: Int -> Expr Int
+        Plus :: Expr Int -> Expr Int -> Expr Int
+        Eq :: Expr Int -> Expr Int -> Expr Bool
+```
+
+### DerivDecl
+
+``` haskell
+deriving instance Eq a => Eq (Sum a)
+
+deriving instance {-# OVERLAP #-} Eq a => Eq (Sum a)
+
+deriving stock instance {-# OVERLAPS #-} Eq a => Eq (Sum a)
+
+deriving anyclass instance {-# OVERLAPPING #-} Eq a => Eq (Sum a)
+
+deriving newtype instance {-# OVERLAPPABLE #-} Eq a => Eq (Sum a)
+```
+
+### InfixDecl
+
+``` haskell
+infix 4 ==, /=, <, <=, >, >=
+
+infixr 0 $
+
+infixl !!
+```
+
+### DefaultDecl
+
+``` haskell
+default ()
+
+default ( Integer, Double )
+```
+
+### SpliceDecl
+
+``` haskell
+$foo
+
+$( bar baz )
+```
+
+### TypeSig
+
+``` haskell
+id :: a -> a
+sort :: Ord a => [ a ] -> [ a ]
+long :: ( IsString a, Monad m ) => ByteString
+    -> ByteString -> ByteString -> ByteString -> ByteString -> a -> m ()
+mktime :: Int -- hours
+    -> Int -- minutes
+    -> Int -- seconds
+    -> Time
+transform :: forall a. St -> State St a -> EitherT ServantErr IO a
+```
+
+### PatSyn and PatSynSig
+
+``` haskell
+{-# LANGUAGE PatternSynonyms #-}
+
+pattern MyJust :: a -> Maybe a
+pattern MyJust a = Just a
+
+pattern MyPoint :: Int -> Int -> ( Int, Int )
+pattern MyPoint { x, y } = ( x, y )
+
+pattern ErrorCall :: String -> ErrorCall
+pattern ErrorCall s <- ErrorCallWithLocation s _
+  where
+    ErrorCall s = ErrorCallWithLocation s ""
+
+pattern IsTrue :: Show a => a
+pattern IsTrue <- ((== "True") . show -> True)
+
+pattern ExNumPat :: () => Show b => b -> T
+pattern ExNumPat x = MkT x
+
+pattern Foo, Bar :: Show a => a
+```
+
+### FunBind and PatBind
+
+``` haskell
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE RecordWildCards #-}
+
+pi = 3.14
+
+id x = x
+
+not False = True
+not _ = False
+
+head (x : _) = x
+
+maybe x _ Nothing = x
+maybe _ f (Some x) = f x
+
+fst ( x, _ ) = x
+
+fst' (# x, _ #) = x
+
+fstPrism (# x | | #) = Just x
+fstPrism (# | _ | #) = Nothing
+fstPrism (# | | _ #) = Nothing
+
+empty [] = True
+empty _ = False
+
+unSum (Sum { getSum = s }) = s
+
+mag2 Point { x, y } = sqr x + sqr y
+mag2 Point { .. } = sqr x + sqr y
+
+strict !x = x
+
+irrefutable ~x = x
+
+(//) a b = undefined
+
+a // b = undefined
+
+main = do
+    greet "World"
+  where
+    greet who = putStrLn $ "Hello, " ++ who ++ "!"
+```
+
+### ForImp and ForExp
+
+``` haskell
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+foreign import ccall sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall unsafe exit :: Double -> Double
+
+foreign export ccall callback :: Int -> Int
+```
+
+### Pragmas
+
+``` haskell
+{-# RULES #-}
+
+{-# RULES "map/map" forall f g xs. map f (map g xs) = map (f . g) xs #-}
+
+{-# RULES "map/append" [2] forall f xs ys. map f (xs ++ ys)
+          = map f xs ++ map f ys #-}
+
+{-# DEPRECATED #-}
+{-# DEPRECATED foo "use bar instead" #-}
+{-# DEPRECATED foo, bar, baz "no longer supported" #-}
+{-# WARNING #-}
+{-# WARNING foo "use bar instead" #-}
+{-# WARNING foo, bar, baz "no longer supported" #-}
+{-# INLINE foo #-}
+{-# INLINE [3] foo #-}
+{-# INLINE [~3] foo #-}
+{-# NOINLINE foo #-}
+{-# INLINE CONLIKE foo #-}
+{-# INLINE CONLIKE [3] foo #-}
+{-# SPECIALISE foo :: Int -> Int #-}
+{-# SPECIALISE [3] foo :: Int -> Int, Float -> Float #-}
+{-# SPECIALISE INLINE foo :: Int -> Int #-}
+{-# SPECIALISE NOINLINE foo :: Int -> Int #-}
+{-# SPECIALISE instance Foo Int #-}
+{-# SPECIALISE instance forall a. (Ord a) => Foo a #-}
+{-# ANN foo (Just "Foo") #-}
+{-# ANN type Foo (Just "Foo") #-}
+{-# ANN module (Just "Foo") #-}
+{-# MINIMAL foo | bar, (baz | quux) #-}
+```
+
+## Exp
+
+### Var, Con, Lit, Tuple, UnboxedSum, List, and ExpTypeSig
+
+``` haskell
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+
+foo = foo
+
+foo = Nothing
+
+foo = 123
+
+foo = 'x'
+
+foo = ""
+
+foo = "Lorem Ipsum Dolor Amet Sit"
+
+foo = ()
+
+foo = ( 1, 2 )
+
+foo = ( 1 -- the one
+      , 2
+      )
+
+foo = ( 1,  )
+
+foo = ( , 2 )
+
+foo = ( , 2,  )
+
+foo = (# #)
+
+foo = (# 1, 2 #)
+
+foo = (# 1 -- the one
+       , 2
+      #)
+
+foo = (# 1 #)
+
+foo = (# | 1 | | #)
+
+foo = (# | 1 -- the one
+      | |
+      #)
+
+foo = []
+
+foo = [ 1 ]
+
+foo = [ 1, 2 ]
+
+foo = [ 1 -- the one
+      , 2
+      ]
+
+foo = 1 :: Int
+```
+
+### App, InfixApp, NegApp, LeftSection, RightSection
+
+``` haskell
+foo = foldl fn init list
+
+foo = foldl fn -- reducer
+    init -- initial value
+    list
+
+foo = 1 + 2
+
+foo = fn `map` list
+
+foo = -3
+
+foo = (+ arg)
+
+foo = (`op` arg)
+
+foo = (arg +)
+
+foo = (arg `op`)
+```
+
+### EnumFrom, EnumFromTo, EnumFromThen, EnumFromThenTo, ParArrayFromTo, ParArrayFromThenTo
+
+``` haskell
+foo = [ 1 .. ]
+
+foo = [ 1 .. 10 ]
+
+foo = [ 1, 2 .. ]
+
+foo = [ 1, 2 .. 10 ]
+
+foo = [: 1 .. 10 :]
+
+foo = [: 1, 2 .. 10 :]
+```
+
+### ListComp, ParComp, and ParArrayComp
+
+``` haskell
+{-# LANGUAGE TransformListComp #-}
+
+foo = [ ( x, y ) | x <- xs, y <- ys ]
+
+foo = [ ( x, y ) -- cartesian product
+      | x <- xs -- first list
+      , y <- ys -- second list
+      ]
+
+foo = [ ( x, y ) | x <- xs | y <- ys ]
+
+foo = [ ( x, y ) -- zip
+      | x <- xs -- first list
+      | y <- ys -- second list
+      ]
+
+foo = [: ( x, y ) | x <- xs | y <- ys :]
+
+foo = [: ( x, y ) -- zip
+      | x <- xs -- first list
+      | y <- ys -- second list
+      :]
+
+foo = [ ( x, y ) | x <- xs
+                 , y <- ys
+                 , then reverse
+                 , then sortWith by (x + y)
+                 , then group using permutations
+                 , then group by (x + y) using groupWith
+      ]
+```
+
+### RecConstr and RecUpdate
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+
+foo = Point { x = 1, y = 2 }
+
+foo = Point { x = 1 -- the one
+    , y, .. }
+
+foo = bar { x = 1 }
+
+foo = bar { x = 1 -- the one
+    , y, .. }
+```
+
+### Let, If, MultiIf, and Case
+
+``` haskell
+{-# LANGUAGE MultiWayIf #-}
+
+foo = let x = x in x
+
+foo = let x = x -- bottom
+    in 
+        -- bottom
+        x
+
+foo = if null xs then None else Some $ head xs
+
+foo = if null xs -- condition
+    then None -- it's empty
+    else Some $ head xs -- it's not
+
+foo = if
+    | null xs -> None
+    | otherwise -> Some $ head xs
+
+foo = if
+    | null xs ->
+        -- it's empty
+        None
+    | otherwise ->
+        -- it's not
+        Some $ head x
+
+foo = case x of
+    True -> False
+    False -> True
+
+foo = case xs of
+    [] ->
+        -- it's empty
+        None
+    x : _ ->
+        -- it's not
+        Some x
+
+foo = case xs of
+    _
+        | null xs -> None
+    _ -> Some $ head x
+```
+
+### Do and MDo
+
+``` haskell
+{-# LANGUAGE RecursiveDo #-}
+
+foo = do
+    return ()
+
+foo = do
+    return ()
+
+foo = do
+    this <- that
+    let this' = tail this
+    if this -- condition
+        then that else those
+
+foo = mdo
+    return ()
+```
+
+### Lambda, LCase
+
+``` haskell
+{-# LANGUAGE LambdaCase #-}
+
+foo = \x -> x
+
+foo = \ ~x -> x
+
+foo = \ !x -> x
+
+foo d = \case
+    Nothing -> d
+    Some x -> x
+```
+
+### BracketExp, SpliceExp, QuasiQuote, VarQuote, and TypQuote
+
+``` haskell
+{-# LANGUAGE TemplateHaskell #-}
+
+mkDecl :: Q Decl
+mkDecl = [d| id x = x |]
+
+mkType :: Q Type
+mkType = [t| ( a, b ) -> a |]
+
+mkPat :: Q Pat
+mkPat = [p| ( a, b ) |]
+
+mkExp :: Q Exp
+mkExp = [| a |]
+
+fst :: $( mkType )
+fst $( mkPat ) = $( mkExp )
+
+html = [html|<p>Lorem Ipsum Dolor Amet Sit</p>|]
+
+foo = mkSomething 'id 'Nothing ''Maybe
+```
+
+# Regression Tests
+
+## Do
+
+Before comments and onside indent do not mix well.
+
+``` haskell
+foo = do
+    -- comment
+    some expression
+```
+
+## Types
+
+Long types allow linebreaks.
+
+``` haskell
+newtype MyMonadT a b m
+    = MyMonad { runMyMonad :: StateT ([ ( a, a -> b ) ])
+          (ReaderT a (ExceptT [ IM.IntMap b ]) (WriterT [ IS.IntSet x ] m)) }
+```
+
+Promoted types.
+
+``` haskell
+type Foo = Bar 1 "foo" '() '( A, B ) '[ X, Y ]
+```
+
+## Patterns
+
+Long function pattern matches allow linebreaks.
+
+``` haskell
+doThing (Constructor field1 field2 field3) (Constructor field1 field2 field3)
+    (Constructor field1 field2 field3) = undefined
+```
+
+## Onside
+
+Indent within onside started on non-empty line should still not stack.
+
+``` haskell
+foo = if cond then do
+    this else do
+    that
+```
+
+Before comments at the start of onside do not trigger onside.
+
+``` haskell
+foo = do
+    -- comment
+    some expression
+```
+
+Matche arms have individual onside.
+
+``` haskell
+foo True = some -- comment
+    expression
+foo False = some -- comment
+    other expression
+```
+
+Where binds are considered outside of onside.
+
+``` haskell
+foo = some -- comment
+    expression
+  where
+    expression = other
+```
+
+Align overrides onside.
+
+``` haskell
+foo = some expr [ 1 -- comment
+                , 2
+                ]
+```
+
+If-then-else must always indent in do blocks.
+
+``` haskell
+foo = do
+    if condition -- comment
+        then this else that
+```
+
+Lists must not suppress onside.
+
+``` haskell
+foo = case x of
+    [ y -- comment
+        , z
+        ] -> bar
+
+foo = do
+    [ x -- comment
+        , y
+        ]
+```
+
+## Comments
+
+Don't be too eager in assigning comments to the following AST node.
+
+``` haskell
+data Foo = Foo { fooBar :: Text
+               -- ^A comment, long enough to end up on its own line, or at least I hope so.
+           }
+    deriving ( Eq )
+```
+
+Keep comments together and aligned.
+
+``` haskell
+-- block
+-- one
+data Foo = Foo  -- some
+                -- comments
+         | Quux -- more
+                -- comments
+-- block
+-- two
+```
+
+... even when haskell-src-exts has weird column span info.
+
+``` haskell
+module Main where
+
+-- comment
+instance Foo Bar where
+    foo = undefined
+
+bar = undefined
+```
+
+Only comments.
+
+``` haskell
+-- some comment
+```
+
+Make sure no comments are dropped from operators or argument.
+
+``` haskell
+foo = some -- comment 1
+    -- comment 2
+    %~ -- comment 3
+    argument -- comment 4
+```
+
+Comments after `where` stay there.
+
+``` haskell
+consM :: Monad m => m a -> Stream m a -> Stream m a
+consM m (Stream step state) = Stream step1 Nothing
+  where
+    {-# INLINE_LATE step1 #-}
+    step1 _ _ = undefined
+```
+
+Comments between declarations do not cause empty lines.
+
+``` haskell
+f :: ()
+--
+f = ()
+```
+
+## Indentation and Line Prefixes
+
+Preserving indentation and line prefixes so that Floskell can be run
+on individual declarations and quoted haskell code.
+
+``` haskell
+    data Enum = One   -- Foo
+              | Two   -- Bar
+              | Three -- Baz
+```
+
+``` haskell
+>
+>    data Enum = One   -- Foo
+>              | Two   -- Bar
+>              | Three -- Baz
+>
+```
+
+## Module Exports
+
+Long module exports don't force overlong line.
+
+``` haskell
+module SimpleFunctions ( identity, compose, append, firstElement
+                       , secondElem ) where
+```
diff --git a/styles/chris-done.md b/styles/chris-done.md
new file mode 100644
--- /dev/null
+++ b/styles/chris-done.md
@@ -0,0 +1,1027 @@
+# Introduction
+
+This file acts both as a presentation of the Floskell formatting
+styles, as well as a set of regression tests.
+
+You can see how a particular style will format Haskell source by
+reading the matching Markdown file in the styles/ directory.
+
+For regression testing, the canonical source, TEST.md in the root
+directory, is parsed and each Haskell code block formatted according
+to all predefined styles.  The formatted output is then compared with
+the corresponding, already formatted code block in the <style\>.md file
+in the styles/ subdirectory.
+
+The regression test will also verify that repeated invocations of the
+pretty printer will not modify an already formatted piece of code.
+
+The following code block acts as a quick presentation for the
+different formatting styles, by presenting a mixture of common Haskell
+constructs.
+
+``` haskell
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+{- |
+Module: Style.Haskell.Example
+
+Haskell Code Style Example.
+-}
+module Style.Haskell.Example
+  (-- * Types
+   Enum(..)
+  ,Either(..)
+  ,Point(..)
+   -- * Functions
+  ,hello) where
+
+-- Module imports
+import qualified Control.Monad.Trans.State
+       (State,evalState,execState,get,modify,put,runState)
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import Prelude hiding (map)
+
+-- Data declarations
+data Enum
+  = CaseA
+  | CaseB
+  | CaseC
+  deriving (Eq,Enum,Show)
+
+data Either a b
+  = Left a
+  | Right b
+  deriving (Eq,Show)
+
+data Point =
+  Point {pointX :: Float
+        ,pointY :: Float
+        ,pointLabel :: String}
+  deriving (Eq,Show)
+
+-- Type classes
+class Functor f => Applicative a where
+  pure :: b -> a b
+  ap :: a (b -> c) -> a b -> a c
+
+class Fundep a b | a -> b where
+  convert :: a -> b
+
+instance Functor f => Functor (Wrap f) where
+  fmap f (Wrap x) = Wrap $ fmap f x
+
+-- Values
+origin :: Point
+origin =
+  Point {pointX = 0
+        ,pointY = 0
+        ,pointLabel = "Origin"}
+
+lorem :: [String]
+lorem =
+  ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+  ,"Curabitur nec ante nec mauris ornare suscipit."
+  ,"In ac vulputate libero."
+  ,"Duis eget magna non purus imperdiet molestie nec quis mauris."
+  ,"Praesent blandit quam vel arcu pellentesque, id aliquet turpis faucibus."]
+
+-- Functions
+facs :: [Int]
+facs = [1,1] ++ zipWith (+) (tailfacs)
+
+hello :: MonadIO m => m ()
+hello =
+  do name <- liftIO getLine
+     liftIO . putStrLn $ greetings name
+  where greetings n = "Hello " ++ n ++ "!"
+
+letExpr :: Point -> String
+letExp x =
+  let y = 1
+      z = 2
+  in if x > 0
+        then y
+        else z
+
+ifExpr :: Bool -> Bool
+ifExpr b =
+  if b == True
+     then False
+     else True
+
+caseExpr :: [a] -> Maybe a
+caseExpr xs =
+  case xs of
+    [] -> Nothing
+    (x:_) -> Just x
+
+guarded :: Int -> Int
+guarded x
+  | x == 0 = 1
+  | x == 1 = 1
+  | otherwise = guarded (x - 2) + guarded (x - 1)
+
+someLongFunctionNameWithALotOfParameters
+  :: (MonadIO m,MonadRandom m) => String -> (String -> String) -> m ()
+someLongFunctionNameWithALotOfParameters = undefined
+```
+
+# Unit Tests
+
+## ModuleHead and ExportSpecList
+
+Without exports
+
+``` haskell
+module Main where
+```
+
+With exports
+
+``` haskell
+module Main (foo,bar,baz,main) where
+```
+
+With exports and comments
+
+``` haskell
+module Main
+  (-- * Main Program
+   main
+   -- * Functions
+  ,foo -- foo function
+  ,bar -- bar function
+  ,baz -- baz function
+  ) where
+```
+
+With deprecation
+
+``` haskell
+module Main {-# DEPRECATED "no longer supported" #-} where
+```
+
+With warnings
+
+``` haskell
+module Main {-# WARNING "do not use" #-} where
+```
+
+## ImportDecl
+
+``` haskell
+import Prelude
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.ByteString (ByteString,pack,unpack)
+import qualified Data.ByteString as BS (pack,unpack)
+import Control.Monad hiding (forM)
+import {-# SOURCE #-} safe qualified "foo" Foo as F
+```
+
+## Decl
+
+### TypeDecl
+
+``` haskell
+type Name = String
+
+type Pair a = (a,a)
+
+type Fun a b = a -> b
+```
+
+### DataDecl and GDataDecl
+
+``` haskell
+data Void
+
+data Unit = Unit
+
+data Maybe a
+  = Nothing
+  | Just a
+
+data Num a => SomeNum = SomeNum a
+
+newtype RWS r w s = RWS (ReaderT r (WriterT w (StateT s Identity)))
+  deriving (Functor,Applicative,Monad)
+
+data Enum
+  = One   -- Foo
+  | Two   -- Bar
+  | Three -- Baz
+
+data Foo
+  deriving ()
+
+data Foo
+  deriving Show
+
+data Foo
+  deriving (Show)
+
+data Foo
+  deriving (Eq,Ord)
+
+data Expr :: * -> * where
+  Const :: Int -> Expr Int
+  Plus :: Expr Int -> Expr Int -> Expr Int
+  Eq :: Expr Int -> Expr Int -> Expr Bool
+  deriving (Show)
+
+data Term a where
+  Lit :: {val :: Int} -> Term Int
+  Succ :: {num :: Term Int} -> Term Int
+  Pred :: {num :: Term Int} -> Term Int
+  IsZero :: {arg :: Term Int} -> Term Bool
+  Pair :: {arg1 :: Term a
+          ,arg2 :: Term b} -> Term (a,b)
+  If :: {cnd :: Term Bool
+        ,tru :: Term a
+        ,fls :: Term a} -> Term a
+```
+
+### TypeFamDecl, TypeInsDecl, and ClosedTypeFamDecl
+
+``` haskell
+type family Mutable v
+
+type family Mutable v = (r :: *)
+
+type family Mutable v = r | r -> v
+
+type instance Mutable Int = MIntVector
+
+type family Store a where
+  Store Bool = [Int]
+  Store a = [a]
+
+type family Store a = (r :: *) where
+  Store a = [a]
+
+type family Store a = r | r -> a where
+  Store a = [a]
+```
+
+### DataFamDecl, DataInsDecl, and GDataInsDecl
+
+``` haskell
+data family List a
+
+data instance List () = NilList Int
+
+data instance List Char
+  = CharNil
+  | CharCons Char (List Char)
+  deriving (Eq,Ord,Show)
+
+data instance List Int :: * where
+  IntNil :: List Int
+  IntCons :: Int -> List Int
+  deriving (Eq,Ord,Show)
+
+data instance List Int :: * where
+  IntNil :: List Int
+  IntCons :: {val :: Int} -> List Int
+  deriving (Eq,Ord,Show)
+
+newtype Penalty = Penalty Int
+  deriving (Eq,Ord)
+  deriving stock (Read,Show)
+  deriving newtype (Num)
+  deriving anyclass (FromJSON,ToJSON)
+  deriving (Semigroup,Monoid) via M.Sum Int
+```
+
+### ClassDecl and InstDecl
+
+``` haskell
+class Monoid a where
+  mempty :: a
+  mappend :: a -> a -> a
+
+class Applicative m => Monad m where
+  fail :: m a
+  return :: a -> m a
+  (>>=) :: a -> (a -> m b) -> m b
+
+class Monad m => MonadState s m | m -> s where
+  get :: m s
+  put :: s -> m ()
+  state :: (s -> (a,s)) -> m a
+
+class ToJSON a where
+  toJSON :: a -> Value
+  default toJSON :: (Generic a,GToJSON (Rep a)) => a -> Value
+  toJSON = genericToJSON defaultOptions
+
+instance ToJSON ()
+
+instance Bounded Bool where
+  minBound = False
+
+  maxBound = True
+
+instance Semigroup a => Monoid (Maybe a) where
+  mempty = Nothing
+
+  Nothing `mappend` m = m
+  m `mappend` Nothing = m
+  Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
+
+instance Data () where
+  type Base = ()
+
+  newtype Wrapped = Wrapped {unWrap :: ()}
+
+  data Expr :: * -> * where
+    Const :: Int -> Expr Int
+    Plus :: Expr Int -> Expr Int -> Expr Int
+    Eq :: Expr Int -> Expr Int -> Expr Bool
+```
+
+### DerivDecl
+
+``` haskell
+deriving instance Eq a => Eq (Sum a)
+
+deriving instance {-# OVERLAP #-} Eq a => Eq (Sum a)
+
+deriving stock instance {-# OVERLAPS #-} Eq a => Eq (Sum a)
+
+deriving anyclass instance {-# OVERLAPPING #-} Eq a => Eq (Sum a)
+
+deriving newtype instance {-# OVERLAPPABLE #-} Eq a => Eq (Sum a)
+```
+
+### InfixDecl
+
+``` haskell
+infix 4 ==,/=,<,<=,>,>=
+
+infixr 0 $
+
+infixl !!
+```
+
+### DefaultDecl
+
+``` haskell
+default ()
+
+default (Integer,Double)
+```
+
+### SpliceDecl
+
+``` haskell
+$foo
+
+$(bar baz)
+```
+
+### TypeSig
+
+``` haskell
+id :: a -> a
+sort :: Ord a => [a] -> [a]
+long :: (IsString a,Monad m)
+     => ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> a
+     -> m ()
+mktime :: Int -- hours
+       -> Int -- minutes
+       -> Int -- seconds
+       -> Time
+transform :: forall a. St -> State St a -> EitherT ServantErr IO a
+```
+
+### PatSyn and PatSynSig
+
+``` haskell
+{-# LANGUAGE PatternSynonyms #-}
+
+pattern MyJust :: a -> Maybe a
+pattern MyJust a = Just a
+
+pattern MyPoint :: Int -> Int -> (Int,Int)
+pattern MyPoint {x,y} = (x,y)
+
+pattern ErrorCall :: String -> ErrorCall
+pattern ErrorCall s <- ErrorCallWithLocation s _
+  where ErrorCall s = ErrorCallWithLocation s ""
+
+pattern IsTrue :: Show a => a
+pattern IsTrue <- ((== "True") . show -> True)
+
+pattern ExNumPat :: () => Show b => b -> T
+pattern ExNumPat x = MkT x
+
+pattern Foo,Bar :: Show a => a
+```
+
+### FunBind and PatBind
+
+``` haskell
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE RecordWildCards #-}
+
+pi = 3.14
+
+id x = x
+
+not False = True
+not _ = False
+
+head (x:_) = x
+
+maybe x _ Nothing = x
+maybe _ f (Some x) = f x
+
+fst (x,_) = x
+
+fst' (# x,_ #) = x
+
+fstPrism (# x | | #) = Just x
+fstPrism (# | _ | #) = Nothing
+fstPrism (# | | _ #) = Nothing
+
+empty [] = True
+empty _ = False
+
+unSum (Sum {getSum = s}) = s
+
+mag2 Point {x,y} = sqr x + sqr y
+mag2 Point {..} = sqr x + sqr y
+
+strict !x = x
+
+irrefutable ~x = x
+
+(//) a b = undefined
+
+a // b = undefined
+
+main = do greet "World"
+  where greet who = putStrLn $ "Hello, " ++ who ++ "!"
+```
+
+### ForImp and ForExp
+
+``` haskell
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+foreign import ccall sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall unsafe exit :: Double -> Double
+
+foreign export ccall callback :: Int -> Int
+```
+
+### Pragmas
+
+``` haskell
+{-# RULES #-}
+
+{-# RULES "map/map" forall f g xs. map f (map g xs) = map (f . g) xs #-}
+
+{-# RULES "map/append" [2] forall f xs ys. map f (xs ++ ys) =
+          map f xs ++ map f ys #-}
+
+{-# DEPRECATED #-}
+{-# DEPRECATED foo "use bar instead" #-}
+{-# DEPRECATED foo,bar,baz "no longer supported" #-}
+{-# WARNING #-}
+{-# WARNING foo "use bar instead" #-}
+{-# WARNING foo,bar,baz "no longer supported" #-}
+{-# INLINE foo #-}
+{-# INLINE [3] foo #-}
+{-# INLINE [~3] foo #-}
+{-# NOINLINE foo #-}
+{-# INLINE CONLIKE foo #-}
+{-# INLINE CONLIKE [3] foo #-}
+{-# SPECIALISE foo :: Int -> Int #-}
+{-# SPECIALISE [3] foo :: Int -> Int,Float -> Float #-}
+{-# SPECIALISE INLINE foo :: Int -> Int #-}
+{-# SPECIALISE NOINLINE foo :: Int -> Int #-}
+{-# SPECIALISE instance Foo Int #-}
+{-# SPECIALISE instance forall a. (Ord a) => Foo a #-}
+{-# ANN foo (Just "Foo") #-}
+{-# ANN type Foo (Just "Foo") #-}
+{-# ANN module (Just "Foo") #-}
+{-# MINIMAL foo | bar,(baz | quux) #-}
+```
+
+## Exp
+
+### Var, Con, Lit, Tuple, UnboxedSum, List, and ExpTypeSig
+
+``` haskell
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+
+foo = foo
+
+foo = Nothing
+
+foo = 123
+
+foo = 'x'
+
+foo = ""
+
+foo = "Lorem Ipsum Dolor Amet Sit"
+
+foo = ()
+
+foo = (1,2)
+
+foo =
+  (1 -- the one
+  ,2)
+
+foo = (1,)
+
+foo = (,2)
+
+foo = (,2,)
+
+foo = (# #)
+
+foo = (# 1,2 #)
+
+foo =
+  (# 1 -- the one
+    ,2 #)
+
+foo = (# 1 #)
+
+foo = (# | 1 | | #)
+
+foo =
+  (# | 1 -- the one
+  | | #)
+
+foo = []
+
+foo = [1]
+
+foo = [1,2]
+
+foo =
+  [1 -- the one
+  ,2]
+
+foo = 1 :: Int
+```
+
+### App, InfixApp, NegApp, LeftSection, RightSection
+
+``` haskell
+foo = foldl fn init list
+
+foo =
+  foldl fn -- reducer
+        init -- initial value
+        list
+
+foo = 1 + 2
+
+foo = fn `map` list
+
+foo = -3
+
+foo = (+ arg)
+
+foo = (`op` arg)
+
+foo = (arg +)
+
+foo = (arg `op`)
+```
+
+### EnumFrom, EnumFromTo, EnumFromThen, EnumFromThenTo, ParArrayFromTo, ParArrayFromThenTo
+
+``` haskell
+foo = [1 ..]
+
+foo = [1 .. 10]
+
+foo = [1,2 ..]
+
+foo = [1,2 .. 10]
+
+foo = [:1 .. 10:]
+
+foo = [:1,2 .. 10:]
+```
+
+### ListComp, ParComp, and ParArrayComp
+
+``` haskell
+{-# LANGUAGE TransformListComp #-}
+
+foo = [(x,y) | x <- xs,y <- ys]
+
+foo =
+  [(x,y) -- cartesian product
+  | x <- xs -- first list
+   ,y <- ys -- second list
+  ]
+
+foo = [(x,y) | x <- xs | y <- ys]
+
+foo =
+  [(x,y) -- zip
+  | x <- xs -- first list
+  | y <- ys -- second list
+  ]
+
+foo = [:(x,y) | x <- xs | y <- ys:]
+
+foo =
+  [:(x,y) -- zip
+  | x <- xs -- first list
+  | y <- ys -- second list
+  :]
+
+foo =
+  [(x,y) | x <- xs
+          ,y <- ys
+          ,then reverse
+          ,then sortWith by (x + y)
+          ,then group using permutations
+          ,then group by (x + y) using groupWith]
+```
+
+### RecConstr and RecUpdate
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+
+foo =
+  Point {x = 1
+        ,y = 2}
+
+foo =
+  Point {x = 1 -- the one
+        ,y
+        ,..}
+
+foo = bar {x = 1}
+
+foo =
+  bar {x = 1 -- the one
+      ,y
+      ,..}
+```
+
+### Let, If, MultiIf, and Case
+
+``` haskell
+{-# LANGUAGE MultiWayIf #-}
+
+foo =
+  let x = x
+  in x
+
+foo =
+  let x = x -- bottom
+  in
+     -- bottom
+     x
+
+foo =
+  if null xs
+     then None
+     else Some $ head xs
+
+foo =
+  if null xs -- condition
+     then None -- it's empty
+     else Some $ head xs -- it's not
+
+foo =
+  if
+    | null xs -> None
+    | otherwise -> Some $ head xs
+
+foo =
+  if
+    | null xs ->
+      -- it's empty
+      None
+    | otherwise ->
+      -- it's not
+      Some $ head x
+
+foo =
+  case x of
+    True -> False
+    False -> True
+
+foo =
+  case xs of
+    [] ->
+      -- it's empty
+      None
+    x:_ ->
+      -- it's not
+      Some x
+
+foo =
+  case xs of
+    _
+      | null xs -> None
+    _ -> Some $ head x
+```
+
+### Do and MDo
+
+``` haskell
+{-# LANGUAGE RecursiveDo #-}
+
+foo = do return ()
+
+foo = do return ()
+
+foo =
+  do this <- that
+     let this' = tail this
+     if this -- condition
+        then that
+        else those
+
+foo = mdo return ()
+```
+
+### Lambda, LCase
+
+``` haskell
+{-# LANGUAGE LambdaCase #-}
+
+foo = \x -> x
+
+foo = \ ~x -> x
+
+foo = \ !x -> x
+
+foo d =
+  \case
+    Nothing -> d
+    Some x -> x
+```
+
+### BracketExp, SpliceExp, QuasiQuote, VarQuote, and TypQuote
+
+``` haskell
+{-# LANGUAGE TemplateHaskell #-}
+
+mkDecl :: Q Decl
+mkDecl = [d|id x = x|]
+
+mkType :: Q Type
+mkType = [t|(a,b) -> a|]
+
+mkPat :: Q Pat
+mkPat = [p|(a,b)|]
+
+mkExp :: Q Exp
+mkExp = [|a|]
+
+fst :: $(mkType)
+fst $(mkPat) = $(mkExp)
+
+html = [html|<p>Lorem Ipsum Dolor Amet Sit</p>|]
+
+foo = mkSomething 'id 'Nothing ''Maybe
+```
+
+# Regression Tests
+
+## Do
+
+Before comments and onside indent do not mix well.
+
+``` haskell
+foo =
+  do
+       -- comment
+       some expression
+```
+
+## Types
+
+Long types allow linebreaks.
+
+``` haskell
+newtype MyMonadT a b m =
+  MyMonad {runMyMonad :: StateT ([(a,a -> b)])
+                                (ReaderT a
+                                         (ExceptT [IM.IntMap b])
+                                         (WriterT [IS.IntSet x] m))}
+```
+
+Promoted types.
+
+``` haskell
+type Foo = Bar 1 "foo" '() '(A,B) '[X,Y]
+```
+
+## Patterns
+
+Long function pattern matches allow linebreaks.
+
+``` haskell
+doThing (Constructor field1 field2 field3)
+        (Constructor field1 field2 field3)
+        (Constructor field1 field2 field3) = undefined
+```
+
+## Onside
+
+Indent within onside started on non-empty line should still not stack.
+
+``` haskell
+foo =
+  if cond
+     then do this
+     else do that
+```
+
+Before comments at the start of onside do not trigger onside.
+
+``` haskell
+foo =
+  do
+       -- comment
+       some expression
+```
+
+Matche arms have individual onside.
+
+``` haskell
+foo True =
+  some -- comment
+  expression
+foo False =
+  some -- comment
+  other
+  expression
+```
+
+Where binds are considered outside of onside.
+
+``` haskell
+foo =
+  some -- comment
+  expression
+  where expression = other
+```
+
+Align overrides onside.
+
+``` haskell
+foo =
+  some expr
+       [1 -- comment
+       ,2]
+```
+
+If-then-else must always indent in do blocks.
+
+``` haskell
+foo =
+  do if condition -- comment
+        then this
+        else that
+```
+
+Lists must not suppress onside.
+
+``` haskell
+foo =
+  case x of
+    [y -- comment
+      ,z] -> bar
+
+foo =
+  do [x -- comment
+       ,y]
+```
+
+## Comments
+
+Don't be too eager in assigning comments to the following AST node.
+
+``` haskell
+data Foo =
+  Foo {fooBar :: Text
+       -- ^A comment, long enough to end up on its own line, or at least I hope so.
+      }
+  deriving (Eq)
+```
+
+Keep comments together and aligned.
+
+``` haskell
+-- block
+-- one
+data Foo
+  = Foo  -- some
+         -- comments
+  | Quux -- more
+         -- comments
+-- block
+-- two
+```
+
+... even when haskell-src-exts has weird column span info.
+
+``` haskell
+module Main where
+
+-- comment
+instance Foo Bar where
+  foo = undefined
+
+bar = undefined
+```
+
+Only comments.
+
+``` haskell
+-- some comment
+```
+
+Make sure no comments are dropped from operators or argument.
+
+``` haskell
+foo =
+  some -- comment 1
+  -- comment 2
+  %~ -- comment 3
+  argument -- comment 4
+```
+
+Comments after `where` stay there.
+
+``` haskell
+consM :: Monad m => m a -> Stream m a -> Stream m a
+consM m (Stream step state) = Stream step1 Nothing
+  where
+        {-# INLINE_LATE step1 #-}
+        step1 _ _ = undefined
+```
+
+Comments between declarations do not cause empty lines.
+
+``` haskell
+f :: ()
+--
+f = ()
+```
+
+## Indentation and Line Prefixes
+
+Preserving indentation and line prefixes so that Floskell can be run
+on individual declarations and quoted haskell code.
+
+``` haskell
+    data Enum
+      = One   -- Foo
+      | Two   -- Bar
+      | Three -- Baz
+```
+
+``` haskell
+>
+>    data Enum
+>      = One   -- Foo
+>      | Two   -- Bar
+>      | Three -- Baz
+>
+```
+
+## Module Exports
+
+Long module exports don't force overlong line.
+
+``` haskell
+module SimpleFunctions (identity,compose,append,firstElement,secondElem) where
+```
diff --git a/styles/cramer.md b/styles/cramer.md
new file mode 100644
--- /dev/null
+++ b/styles/cramer.md
@@ -0,0 +1,1007 @@
+# Introduction
+
+This file acts both as a presentation of the Floskell formatting
+styles, as well as a set of regression tests.
+
+You can see how a particular style will format Haskell source by
+reading the matching Markdown file in the styles/ directory.
+
+For regression testing, the canonical source, TEST.md in the root
+directory, is parsed and each Haskell code block formatted according
+to all predefined styles.  The formatted output is then compared with
+the corresponding, already formatted code block in the <style\>.md file
+in the styles/ subdirectory.
+
+The regression test will also verify that repeated invocations of the
+pretty printer will not modify an already formatted piece of code.
+
+The following code block acts as a quick presentation for the
+different formatting styles, by presenting a mixture of common Haskell
+constructs.
+
+``` haskell
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+
+{- |
+Module: Style.Haskell.Example
+
+Haskell Code Style Example.
+-}
+module Style.Haskell.Example
+    ( -- * Types
+      Enum(..)
+    , Either(..)
+    , Point(..)
+      -- * Functions
+    , hello
+    ) where
+
+-- Module imports
+import qualified Control.Monad.Trans.State
+                 ( State, evalState, execState, get, modify, put, runState )
+
+import qualified Data.Map                  as Map
+import qualified Data.Text                 as Text
+
+import           Prelude                   hiding ( map )
+
+-- Data declarations
+data Enum = CaseA | CaseB | CaseC
+    deriving ( Eq, Enum, Show )
+
+data Either a b = Left a | Right b
+    deriving ( Eq, Show )
+
+data Point = Point { pointX :: Float, pointY :: Float, pointLabel :: String }
+    deriving ( Eq, Show )
+
+-- Type classes
+class Functor f => Applicative a where
+    pure :: b -> a b
+    ap :: a (b -> c) -> a b -> a c
+
+class Fundep a b | a -> b where
+    convert :: a -> b
+
+instance Functor f => Functor (Wrap f) where
+    fmap f (Wrap x) = Wrap $ fmap f x
+
+-- Values
+origin :: Point
+origin = Point { pointX = 0, pointY = 0, pointLabel = "Origin" }
+
+lorem :: [String]
+lorem =
+    [ "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+    , "Curabitur nec ante nec mauris ornare suscipit."
+    , "In ac vulputate libero."
+    , "Duis eget magna non purus imperdiet molestie nec quis mauris."
+    , "Praesent blandit quam vel arcu pellentesque, id aliquet turpis faucibus."
+    ]
+
+-- Functions
+facs :: [Int]
+facs = [ 1, 1 ] ++ zipWith (+) (tailfacs)
+
+hello :: MonadIO m => m ()
+hello = do
+    name <- liftIO getLine
+    liftIO . putStrLn $ greetings name
+  where
+    greetings n = "Hello " ++ n ++ "!"
+
+letExpr :: Point -> String
+letExp x = let y = 1
+               z = 2
+           in
+               if x > 0 then y else z
+
+ifExpr :: Bool -> Bool
+ifExpr b = if b == True then False else True
+
+caseExpr :: [a] -> Maybe a
+caseExpr xs = case xs of
+    [] -> Nothing
+    (x : _) -> Just x
+
+guarded :: Int -> Int
+guarded x
+    | x == 0 = 1
+    | x == 1 = 1
+    | otherwise = guarded (x - 2) + guarded (x - 1)
+
+someLongFunctionNameWithALotOfParameters
+    :: (MonadIO m, MonadRandom m) => String -> (String -> String) -> m ()
+someLongFunctionNameWithALotOfParameters = undefined
+```
+
+# Unit Tests
+
+## ModuleHead and ExportSpecList
+
+Without exports
+
+``` haskell
+module Main where
+```
+
+With exports
+
+``` haskell
+module Main ( foo, bar, baz, main ) where
+```
+
+With exports and comments
+
+``` haskell
+module Main
+    ( -- * Main Program
+      main
+      -- * Functions
+    , foo -- foo function
+    , bar -- bar function
+    , baz -- baz function
+    ) where
+```
+
+With deprecation
+
+``` haskell
+module Main {-# DEPRECATED "no longer supported" #-} where
+```
+
+With warnings
+
+``` haskell
+module Main {-# WARNING "do not use" #-} where
+```
+
+## ImportDecl
+
+``` haskell
+import           Control.Monad   hiding ( forM )
+
+import qualified Data.ByteString ( ByteString, pack, unpack )
+import qualified Data.ByteString as BS ( pack, unpack )
+import           Data.Text       ( Text )
+import qualified Data.Text       as T
+
+import {-# SOURCE #-} safe qualified "foo" Foo as F
+
+import           Prelude
+```
+
+## Decl
+
+### TypeDecl
+
+``` haskell
+type Name = String
+
+type Pair a = (a, a)
+
+type Fun a b = a -> b
+```
+
+### DataDecl and GDataDecl
+
+``` haskell
+data Void
+
+data Unit = Unit
+
+data Maybe a = Nothing | Just a
+
+data Num a => SomeNum = SomeNum a
+
+newtype RWS r w s = RWS (ReaderT r (WriterT w (StateT s Identity)))
+    deriving ( Functor, Applicative, Monad )
+
+data Enum = One   -- Foo
+          | Two   -- Bar
+          | Three -- Baz
+
+data Foo
+    deriving ()
+
+data Foo
+    deriving Show
+
+data Foo
+    deriving ( Show )
+
+data Foo
+    deriving ( Eq, Ord )
+
+data Expr :: * -> * where
+    Const :: Int -> Expr Int
+    Plus :: Expr Int -> Expr Int -> Expr Int
+    Eq :: Expr Int -> Expr Int -> Expr Bool
+    deriving ( Show )
+
+data Term a where
+    Lit :: { val :: Int } -> Term Int
+    Succ :: { num :: Term Int } -> Term Int
+    Pred :: { num :: Term Int } -> Term Int
+    IsZero :: { arg :: Term Int } -> Term Bool
+    Pair :: { arg1 :: Term a, arg2 :: Term b } -> Term (a, b)
+    If :: { cnd :: Term Bool, tru :: Term a, fls :: Term a } -> Term a
+```
+
+### TypeFamDecl, TypeInsDecl, and ClosedTypeFamDecl
+
+``` haskell
+type family Mutable v
+
+type family Mutable v = (r :: *)
+
+type family Mutable v = r | r -> v
+
+type instance Mutable Int = MIntVector
+
+type family Store a where
+    Store Bool = [Int]
+    Store a = [a]
+
+type family Store a = (r :: *) where
+    Store a = [a]
+
+type family Store a = r | r -> a where
+    Store a = [a]
+```
+
+### DataFamDecl, DataInsDecl, and GDataInsDecl
+
+``` haskell
+data family List a
+
+data instance List () = NilList Int
+
+data instance List Char = CharNil | CharCons Char (List Char)
+    deriving ( Eq, Ord, Show )
+
+data instance List Int :: * where
+    IntNil :: List Int
+    IntCons :: Int -> List Int
+    deriving ( Eq, Ord, Show )
+
+data instance List Int :: * where
+    IntNil :: List Int
+    IntCons :: { val :: Int } -> List Int
+    deriving ( Eq, Ord, Show )
+
+newtype Penalty = Penalty Int
+    deriving ( Eq, Ord )
+    deriving stock ( Read, Show )
+    deriving newtype ( Num )
+    deriving anyclass ( FromJSON, ToJSON )
+    deriving ( Semigroup, Monoid ) via M.Sum Int
+```
+
+### ClassDecl and InstDecl
+
+``` haskell
+class Monoid a where
+    mempty :: a
+    mappend :: a -> a -> a
+
+class Applicative m => Monad m where
+    fail :: m a
+    return :: a -> m a
+    (>>=) :: a -> (a -> m b) -> m b
+
+class Monad m => MonadState s m | m -> s where
+    get :: m s
+    put :: s -> m ()
+    state :: (s -> (a, s)) -> m a
+
+class ToJSON a where
+    toJSON :: a -> Value
+    default toJSON :: (Generic a, GToJSON (Rep a)) => a -> Value
+    toJSON = genericToJSON defaultOptions
+
+instance ToJSON ()
+
+instance Bounded Bool where
+    minBound = False
+
+    maxBound = True
+
+instance Semigroup a => Monoid (Maybe a) where
+    mempty = Nothing
+
+    Nothing `mappend` m = m
+    m `mappend` Nothing = m
+    Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
+
+instance Data () where
+    type Base = ()
+
+    newtype Wrapped = Wrapped { unWrap :: () }
+
+    data Expr :: * -> * where
+        Const :: Int -> Expr Int
+        Plus :: Expr Int -> Expr Int -> Expr Int
+        Eq :: Expr Int -> Expr Int -> Expr Bool
+```
+
+### DerivDecl
+
+``` haskell
+deriving instance Eq a => Eq (Sum a)
+
+deriving instance {-# OVERLAP #-} Eq a => Eq (Sum a)
+
+deriving stock instance {-# OVERLAPS #-} Eq a => Eq (Sum a)
+
+deriving anyclass instance {-# OVERLAPPING #-} Eq a => Eq (Sum a)
+
+deriving newtype instance {-# OVERLAPPABLE #-} Eq a => Eq (Sum a)
+```
+
+### InfixDecl
+
+``` haskell
+infix 4 ==, /=, <, <=, >, >=
+
+infixr 0 $
+
+infixl !!
+```
+
+### DefaultDecl
+
+``` haskell
+default ()
+
+default ( Integer, Double )
+```
+
+### SpliceDecl
+
+``` haskell
+$foo
+
+$(bar baz)
+```
+
+### TypeSig
+
+``` haskell
+id :: a -> a
+sort :: Ord a => [a] -> [a]
+long :: (IsString a, Monad m)
+     => ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> a
+     -> m ()
+mktime :: Int -- hours
+       -> Int -- minutes
+       -> Int -- seconds
+       -> Time
+transform :: forall a. St -> State St a -> EitherT ServantErr IO a
+```
+
+### PatSyn and PatSynSig
+
+``` haskell
+{-# LANGUAGE PatternSynonyms #-}
+
+pattern MyJust :: a -> Maybe a
+pattern MyJust a = Just a
+
+pattern MyPoint :: Int -> Int -> (Int, Int)
+pattern MyPoint{x, y} = (x, y)
+
+pattern ErrorCall :: String -> ErrorCall
+pattern ErrorCall s <- ErrorCallWithLocation s _
+  where
+    ErrorCall s = ErrorCallWithLocation s ""
+
+pattern IsTrue :: Show a => a
+pattern IsTrue <- ((== "True") . show -> True)
+
+pattern ExNumPat :: () => Show b => b -> T
+pattern ExNumPat x = MkT x
+
+pattern Foo, Bar :: Show a => a
+```
+
+### FunBind and PatBind
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE UnboxedTuples #-}
+
+pi = 3.14
+
+id x = x
+
+not False = True
+not _ = False
+
+head (x : _) = x
+
+maybe x _ Nothing = x
+maybe _ f (Some x) = f x
+
+fst (x, _) = x
+
+fst' (# x, _ #) = x
+
+fstPrism (# x | | #) = Just x
+fstPrism (# | _ | #) = Nothing
+fstPrism (# | | _ #) = Nothing
+
+empty [] = True
+empty _ = False
+
+unSum (Sum{getSum = s}) = s
+
+mag2 Point{x, y} = sqr x + sqr y
+mag2 Point{..} = sqr x + sqr y
+
+strict !x = x
+
+irrefutable ~x = x
+
+(//) a b = undefined
+
+a // b = undefined
+
+main = do
+    greet "World"
+  where
+    greet who = putStrLn $ "Hello, " ++ who ++ "!"
+```
+
+### ForImp and ForExp
+
+``` haskell
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+foreign import ccall sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall unsafe exit :: Double -> Double
+
+foreign export ccall callback :: Int -> Int
+```
+
+### Pragmas
+
+``` haskell
+{-# RULES #-}
+
+{-# RULES "map/map" forall f g xs. map f (map g xs) = map (f . g) xs #-}
+
+{-# RULES "map/append" [2] forall f xs ys. map f (xs ++ ys) =
+          map f xs ++ map f ys #-}
+
+{-# DEPRECATED #-}
+{-# DEPRECATED foo "use bar instead" #-}
+{-# DEPRECATED foo, bar, baz "no longer supported" #-}
+
+{-# WARNING #-}
+{-# WARNING foo "use bar instead" #-}
+{-# WARNING foo, bar, baz "no longer supported" #-}
+
+{-# INLINE foo #-}
+{-# INLINE [3] foo #-}
+{-# INLINE [~3] foo #-}
+{-# NOINLINE foo #-}
+
+{-# INLINE CONLIKE foo #-}
+{-# INLINE CONLIKE [3] foo #-}
+
+{-# SPECIALISE foo :: Int -> Int #-}
+{-# SPECIALISE [3] foo :: Int -> Int, Float -> Float #-}
+
+{-# SPECIALISE INLINE foo :: Int -> Int #-}
+{-# SPECIALISE NOINLINE foo :: Int -> Int #-}
+
+{-# SPECIALISE instance Foo Int #-}
+{-# SPECIALISE instance forall a. (Ord a) => Foo a #-}
+
+{-# ANN foo (Just "Foo") #-}
+{-# ANN type Foo (Just "Foo") #-}
+{-# ANN module (Just "Foo") #-}
+
+{-# MINIMAL foo | bar, (baz | quux) #-}
+```
+
+## Exp
+
+### Var, Con, Lit, Tuple, UnboxedSum, List, and ExpTypeSig
+
+``` haskell
+{-# LANGUAGE TupleSections #-}
+
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE UnboxedTuples #-}
+
+foo = foo
+
+foo = Nothing
+
+foo = 123
+
+foo = 'x'
+
+foo = ""
+
+foo = "Lorem Ipsum Dolor Amet Sit"
+
+foo = ()
+
+foo = (1, 2)
+
+foo = ( 1 -- the one
+      , 2
+      )
+
+foo = (1, )
+
+foo = (, 2)
+
+foo = (, 2, )
+
+foo = (# #)
+
+foo = (# 1, 2 #)
+
+foo = (# 1 -- the one
+       , 2
+      #)
+
+foo = (# 1 #)
+
+foo = (# | 1 | | #)
+
+foo = (# | 1 -- the one
+      | |
+      #)
+
+foo = []
+
+foo = [ 1 ]
+
+foo = [ 1, 2 ]
+
+foo = [ 1 -- the one
+      , 2
+      ]
+
+foo = 1 :: Int
+```
+
+### App, InfixApp, NegApp, LeftSection, RightSection
+
+``` haskell
+foo = foldl fn init list
+
+foo = foldl fn -- reducer
+            init -- initial value
+            list
+
+foo = 1 + 2
+
+foo = fn `map` list
+
+foo = -3
+
+foo = (+ arg)
+
+foo = (`op` arg)
+
+foo = (arg +)
+
+foo = (arg `op`)
+```
+
+### EnumFrom, EnumFromTo, EnumFromThen, EnumFromThenTo, ParArrayFromTo, ParArrayFromThenTo
+
+``` haskell
+foo = [ 1 .. ]
+
+foo = [ 1 .. 10 ]
+
+foo = [ 1, 2 .. ]
+
+foo = [ 1, 2 .. 10 ]
+
+foo = [: 1 .. 10 :]
+
+foo = [: 1, 2 .. 10 :]
+```
+
+### ListComp, ParComp, and ParArrayComp
+
+``` haskell
+{-# LANGUAGE TransformListComp #-}
+
+foo = [ (x, y) | x <- xs, y <- ys ]
+
+foo = [ (x, y) -- cartesian product
+      | x <- xs -- first list
+      , y <- ys -- second list
+      ]
+
+foo = [ (x, y) | x <- xs | y <- ys ]
+
+foo = [ (x, y) -- zip
+      | x <- xs -- first list
+      | y <- ys -- second list
+      ]
+
+foo = [: (x, y) | x <- xs | y <- ys :]
+
+foo = [: (x, y) -- zip
+      | x <- xs -- first list
+      | y <- ys -- second list
+      :]
+
+foo = [ (x, y)
+      | x <- xs
+      , y <- ys
+      , then reverse
+      , then sortWith by (x + y)
+      , then group using permutations
+      , then group by (x + y) using groupWith
+      ]
+```
+
+### RecConstr and RecUpdate
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+
+foo = Point { x = 1, y = 2 }
+
+foo = Point { x  = 1 -- the one
+            , y
+            , ..
+            }
+
+foo = bar { x = 1 }
+
+foo = bar { x  = 1 -- the one
+          , y
+          , ..
+          }
+```
+
+### Let, If, MultiIf, and Case
+
+``` haskell
+{-# LANGUAGE MultiWayIf #-}
+
+foo = let x = x in x
+
+foo = let x = x -- bottom
+      in
+          -- bottom
+          x
+
+foo = if null xs then None else Some $ head xs
+
+foo = if null xs -- condition
+      then None -- it's empty
+      else Some $ head xs -- it's not
+
+foo = if
+    | null xs -> None
+    | otherwise -> Some $ head xs
+
+foo = if
+    | null xs ->
+        -- it's empty
+        None
+    | otherwise ->
+        -- it's not
+        Some $ head x
+
+foo = case x of
+    True -> False
+    False -> True
+
+foo = case xs of
+    [] ->
+        -- it's empty
+        None
+    x : _ ->
+        -- it's not
+        Some x
+
+foo = case xs of
+    _
+        | null xs -> None
+    _ -> Some $ head x
+```
+
+### Do and MDo
+
+``` haskell
+{-# LANGUAGE RecursiveDo #-}
+
+foo = do
+    return ()
+
+foo = do
+    return ()
+
+foo = do
+    this <- that
+    let this' = tail this
+    if this -- condition
+        then that
+        else those
+
+foo = mdo
+    return ()
+```
+
+### Lambda, LCase
+
+``` haskell
+{-# LANGUAGE LambdaCase #-}
+
+foo = \x -> x
+
+foo = \ ~x -> x
+
+foo = \ !x -> x
+
+foo d = \case
+    Nothing -> d
+    Some x -> x
+```
+
+### BracketExp, SpliceExp, QuasiQuote, VarQuote, and TypQuote
+
+``` haskell
+{-# LANGUAGE TemplateHaskell #-}
+
+mkDecl :: Q Decl
+mkDecl = [d|id x = x|]
+
+mkType :: Q Type
+mkType = [t|(a, b) -> a|]
+
+mkPat :: Q Pat
+mkPat = [p|(a, b)|]
+
+mkExp :: Q Exp
+mkExp = [|a|]
+
+fst :: $(mkType)
+fst $(mkPat) = $(mkExp)
+
+html = [html|<p>Lorem Ipsum Dolor Amet Sit</p>|]
+
+foo = mkSomething 'id 'Nothing ''Maybe
+```
+
+# Regression Tests
+
+## Do
+
+Before comments and onside indent do not mix well.
+
+``` haskell
+foo = do
+    -- comment
+    some expression
+```
+
+## Types
+
+Long types allow linebreaks.
+
+``` haskell
+newtype MyMonadT a b m =
+    MyMonad { runMyMonad :: StateT ([(a, a -> b)])
+                                   (ReaderT a
+                                            (ExceptT [IM.IntMap b])
+                                            (WriterT [IS.IntSet x] m))
+            }
+```
+
+Promoted types.
+
+``` haskell
+type Foo = Bar 1 "foo" '() '(A, B) '[ X, Y ]
+```
+
+## Patterns
+
+Long function pattern matches allow linebreaks.
+
+``` haskell
+doThing (Constructor field1 field2 field3)
+        (Constructor field1 field2 field3)
+        (Constructor field1 field2 field3) = undefined
+```
+
+## Onside
+
+Indent within onside started on non-empty line should still not stack.
+
+``` haskell
+foo = if cond
+      then do
+          this
+      else do
+          that
+```
+
+Before comments at the start of onside do not trigger onside.
+
+``` haskell
+foo = do
+    -- comment
+    some expression
+```
+
+Matche arms have individual onside.
+
+``` haskell
+foo True = some -- comment
+    expression
+foo False = some -- comment
+    other
+    expression
+```
+
+Where binds are considered outside of onside.
+
+``` haskell
+foo = some -- comment
+    expression
+  where
+    expression = other
+```
+
+Align overrides onside.
+
+``` haskell
+foo = some expr
+           [ 1 -- comment
+           , 2
+           ]
+```
+
+If-then-else must always indent in do blocks.
+
+``` haskell
+foo = do
+    if condition -- comment
+        then this
+        else that
+```
+
+Lists must not suppress onside.
+
+``` haskell
+foo = case x of
+    [ y -- comment
+        , z
+        ] -> bar
+
+foo = do
+    [ x -- comment
+        , y
+        ]
+```
+
+## Comments
+
+Don't be too eager in assigning comments to the following AST node.
+
+``` haskell
+data Foo = Foo { fooBar :: Text
+                 -- ^A comment, long enough to end up on its own line, or at least I hope so.
+               }
+    deriving ( Eq )
+```
+
+Keep comments together and aligned.
+
+``` haskell
+-- block
+-- one
+data Foo = Foo  -- some
+                -- comments
+         | Quux -- more
+                -- comments
+-- block
+-- two
+```
+
+... even when haskell-src-exts has weird column span info.
+
+``` haskell
+module Main where
+
+-- comment
+instance Foo Bar where
+    foo = undefined
+
+bar = undefined
+```
+
+Only comments.
+
+``` haskell
+-- some comment
+```
+
+Make sure no comments are dropped from operators or argument.
+
+``` haskell
+foo = some -- comment 1
+    -- comment 2
+    %~ -- comment 3
+    argument -- comment 4
+```
+
+Comments after `where` stay there.
+
+``` haskell
+consM :: Monad m => m a -> Stream m a -> Stream m a
+consM m (Stream step state) = Stream step1 Nothing
+  where
+    {-# INLINE_LATE step1 #-}
+    step1 _ _ = undefined
+```
+
+Comments between declarations do not cause empty lines.
+
+``` haskell
+f :: ()
+--
+f = ()
+```
+
+## Indentation and Line Prefixes
+
+Preserving indentation and line prefixes so that Floskell can be run
+on individual declarations and quoted haskell code.
+
+``` haskell
+    data Enum = One   -- Foo
+              | Two   -- Bar
+              | Three -- Baz
+```
+
+``` haskell
+>
+>    data Enum = One   -- Foo
+>              | Two   -- Bar
+>              | Three -- Baz
+>
+```
+
+## Module Exports
+
+Long module exports don't force overlong line.
+
+``` haskell
+module SimpleFunctions
+    ( identity
+    , compose
+    , append
+    , firstElement
+    , secondElem
+    ) where
+```
diff --git a/styles/fundamental.md b/styles/fundamental.md
new file mode 100644
--- /dev/null
+++ b/styles/fundamental.md
@@ -0,0 +1,1080 @@
+# Introduction
+
+This file acts both as a presentation of the Floskell formatting
+styles, as well as a set of regression tests.
+
+You can see how a particular style will format Haskell source by
+reading the matching Markdown file in the styles/ directory.
+
+For regression testing, the canonical source, TEST.md in the root
+directory, is parsed and each Haskell code block formatted according
+to all predefined styles.  The formatted output is then compared with
+the corresponding, already formatted code block in the <style\>.md file
+in the styles/ subdirectory.
+
+The regression test will also verify that repeated invocations of the
+pretty printer will not modify an already formatted piece of code.
+
+The following code block acts as a quick presentation for the
+different formatting styles, by presenting a mixture of common Haskell
+constructs.
+
+``` haskell
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+{- |
+Module: Style.Haskell.Example
+
+Haskell Code Style Example.
+-}
+module Style.Haskell.Example
+  (
+   -- * Types
+   Enum(..)
+  ,Either(..)
+  ,Point(..)
+  ,
+   -- * Functions
+   hello)
+  where
+
+-- Module imports
+import qualified Control.Monad.Trans.State
+       (State, evalState, execState, get, modify, put, runState)
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import Prelude hiding (map)
+
+-- Data declarations
+data Enum
+  = CaseA
+  | CaseB
+  | CaseC
+  deriving (Eq,Enum,Show)
+
+data Either a b
+  = Left a
+  | Right b
+  deriving (Eq,Show)
+
+data Point =
+  Point {pointX :: Float
+        ,pointY :: Float
+        ,pointLabel :: String}
+  deriving (Eq,Show)
+
+-- Type classes
+class Functor f =>
+      Applicative a where
+  pure :: b -> a b
+  ap :: a (b -> c) -> a b -> a c
+
+class Fundep a b | a -> b where
+  convert :: a -> b
+
+instance Functor f =>
+         Functor (Wrap f) where
+  fmap f (Wrap x) =
+    Wrap $ fmap
+             f
+             x
+
+-- Values
+origin :: Point
+origin =
+  Point {pointX = 
+             0
+        ,pointY = 
+             0
+        ,pointLabel = 
+             "Origin"}
+
+lorem :: [String]
+lorem =
+  ["Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+  ,"Curabitur nec ante nec mauris ornare suscipit."
+  ,"In ac vulputate libero."
+  ,"Duis eget magna non purus imperdiet molestie nec quis mauris."
+  ,"Praesent blandit quam vel arcu pellentesque, id aliquet turpis faucibus."]
+
+-- Functions
+facs :: [Int]
+facs =
+  [1
+  ,1] ++ zipWith
+           (+)
+           (tailfacs)
+
+hello :: MonadIO m =>
+         m ()
+hello =
+  do name <- liftIO
+               getLine
+     liftIO . putStrLn $ greetings
+                           name
+  where greetings n =
+          "Hello " ++ n ++ "!"
+
+letExpr :: Point -> String
+letExp x =
+  let y =
+        1
+      z =
+        2
+  in if x > 0
+        then y
+        else z
+
+ifExpr :: Bool -> Bool
+ifExpr b =
+  if b == True
+     then False
+     else True
+
+caseExpr :: [a] -> Maybe a
+caseExpr xs =
+  case xs of
+    [] ->
+      Nothing
+    (x:_) ->
+      Just
+        x
+
+guarded :: Int -> Int
+guarded x
+  | x == 0 =
+    1
+  | x == 1 =
+    1
+  | otherwise =
+    guarded
+      (x - 2) + guarded
+                  (x - 1)
+
+someLongFunctionNameWithALotOfParameters :: (MonadIO m
+                                            ,MonadRandom m) =>
+                                            String -> (String -> String) -> m ()
+someLongFunctionNameWithALotOfParameters =
+  undefined
+```
+
+# Unit Tests
+
+## ModuleHead and ExportSpecList
+
+Without exports
+
+``` haskell
+module Main where
+```
+
+With exports
+
+``` haskell
+module Main
+  (foo
+  ,bar
+  ,baz
+  ,main)
+  where
+```
+
+With exports and comments
+
+``` haskell
+module Main
+  (
+   -- * Main Program
+   main
+  ,
+   -- * Functions
+   foo -- foo function
+  ,bar -- bar function
+  ,baz -- baz function
+   )
+  where
+```
+
+With deprecation
+
+``` haskell
+module Main {-# DEPRECATED "no longer supported" #-} where
+```
+
+With warnings
+
+``` haskell
+module Main {-# WARNING "do not use" #-} where
+```
+
+## ImportDecl
+
+``` haskell
+import Prelude
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.ByteString (ByteString, pack, unpack)
+import qualified Data.ByteString as BS (pack, unpack)
+import Control.Monad hiding (forM)
+```
+
+## Decl
+
+### TypeDecl
+
+``` haskell
+type Name = String
+
+type Pair a = (a,a)
+
+type Fun a b = a -> b
+```
+
+### DataDecl and GDataDecl
+
+``` haskell
+data Void
+
+data Unit =
+  Unit
+
+data Maybe a
+  = Nothing
+  | Just a
+
+data Num a =>
+     SomeNum =
+  SomeNum a
+
+newtype RWS r w s =
+  RWS (ReaderT r (WriterT w (StateT s Identity)))
+  deriving (Functor,Applicative,Monad)
+
+data Enum
+  = One   -- Foo
+  | Two   -- Bar
+  | Three -- Baz
+
+data Foo
+  deriving ()
+
+data Foo
+  deriving (Show)
+
+data Foo
+  deriving (Show)
+
+data Foo
+  deriving (Eq,Ord)
+
+data Expr :: * -> * where
+        Const :: Int -> Expr Int
+        Plus :: Expr Int -> Expr Int -> Expr Int
+        Eq :: Expr Int -> Expr Int -> Expr Bool
+    deriving (Show)
+
+data Term a where
+        Lit :: {val :: Int} -> Term Int
+        Succ :: {num :: Term Int} -> Term Int
+        Pred :: {num :: Term Int} -> Term Int
+        IsZero :: {arg :: Term Int} -> Term Bool
+        Pair :: {arg1 :: Term a, arg2 :: Term b} -> Term (a, b)
+        If :: {cnd :: Term Bool, tru :: Term a, fls :: Term a} -> Term a
+```
+
+### TypeFamDecl, TypeInsDecl, and ClosedTypeFamDecl
+
+``` haskell
+type family Mutable v
+
+type family Mutable v = (r :: *)
+
+type family Mutable v = r | r -> v
+
+type instance Mutable Int = MIntVector
+
+type family Store a where
+        Store Bool = [Int]
+        Store a = [a]
+
+type family Store a = (r :: *) where
+        Store a = [a]
+
+type family Store a = r | r -> a where
+        Store a = [a]
+```
+
+### DataFamDecl, DataInsDecl, and GDataInsDecl
+
+``` haskell
+data family List a
+
+data instance  List () = NilList Int
+
+data instance  List Char = CharNil
+                         | CharCons Char (List Char)
+                             deriving (Eq, Ord, Show)
+
+data instance  List Int :: * where
+        IntNil :: List Int
+        IntCons :: Int -> List Int
+    deriving (Eq, Ord, Show)
+
+data instance  List Int :: * where
+        IntNil :: List Int
+        IntCons :: {val :: Int} -> List Int
+    deriving (Eq, Ord, Show)
+```
+
+### ClassDecl and InstDecl
+
+``` haskell
+class Monoid a where
+  mempty :: a
+  mappend :: a -> a -> a
+
+class Applicative m =>
+      Monad m where
+  fail :: m a
+  return :: a -> m a
+  (>>=) :: a -> (a -> m b) -> m b
+
+class Monad m =>
+      MonadState s m | m -> s where
+  get :: m s
+  put :: s -> m ()
+  state :: (s -> (a,s)) -> m a
+
+class ToJSON a where
+  toJSON :: a -> Value
+  default toJSON :: (Generic a
+                    ,GToJSON (Rep a)) =>
+                    a -> Value
+  toJSON =
+    genericToJSON
+      defaultOptions
+
+instance ToJSON ()
+
+instance Bounded Bool where
+  minBound =
+    False
+  maxBound =
+    True
+
+instance Semigroup a =>
+         Monoid (Maybe a) where
+  mempty =
+    Nothing
+  Nothing `mappend` m =
+    m
+  m `mappend` Nothing =
+    m
+  Just m1 `mappend` Just m2 =
+    Just
+      (m1 `mappend` m2)
+
+instance Data () where
+  type Base = ()
+  newtype Wrapped = Wrapped{unWrap :: ()}
+  data Expr :: * -> * where
+        Const :: Int -> Expr Int
+        Plus :: Expr Int -> Expr Int -> Expr Int
+        Eq :: Expr Int -> Expr Int -> Expr Bool
+```
+
+### DerivDecl
+
+``` haskell
+deriving instance Eq a => Eq (Sum a)
+
+deriving instance {-# OVERLAP #-} Eq a => Eq (Sum a)
+
+deriving stock instance {-# OVERLAPS #-} Eq a => Eq (Sum a)
+
+deriving anyclass instance {-# OVERLAPPING #-} Eq a => Eq (Sum a)
+
+deriving newtype instance {-# OVERLAPPABLE #-} Eq a => Eq (Sum a)
+```
+
+### InfixDecl
+
+``` haskell
+infix 4 ==, /=, <, <=, >, >=
+
+infixr 0 $
+
+infixl !!
+```
+
+### DefaultDecl
+
+``` haskell
+default ()
+
+default (Integer, Double)
+```
+
+### SpliceDecl
+
+``` haskell
+$foo
+
+$(bar
+    baz)
+```
+
+### TypeSig
+
+``` haskell
+id :: a -> a
+sort :: Ord a =>
+        [a] -> [a]
+long :: (IsString a
+        ,Monad m) =>
+        ByteString -> ByteString -> ByteString -> ByteString -> ByteString -> a -> m ()
+mktime :: Int -- hours
+           -> Int -- minutes
+               -> Int -- seconds
+                   -> Time
+transform :: forall a. St -> State St a -> EitherT ServantErr IO a
+```
+
+### PatSyn and PatSynSig
+
+``` haskell
+{-# LANGUAGE PatternSynonyms #-}
+
+pattern MyJust :: a -> Maybe a
+
+pattern MyJust a = Just a
+
+pattern MyPoint :: Int -> Int -> (Int, Int)
+
+pattern MyPoint{x, y} = (x, y)
+
+pattern ErrorCall :: String -> ErrorCall
+
+pattern ErrorCall s <- ErrorCallWithLocation s _
+  where ErrorCall s = ErrorCallWithLocation s ""
+
+pattern IsTrue :: Show a => a
+
+pattern IsTrue <- ((== "True") . show -> True)
+
+pattern ExNumPat :: () => Show b => b -> T
+
+pattern ExNumPat x = MkT x
+
+pattern Foo, Bar :: Show a => a
+```
+
+### FunBind and PatBind
+
+``` haskell
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE RecordWildCards #-}
+
+pi =
+  3.14
+
+id x =
+  x
+
+not False =
+  True
+not _ =
+  False
+
+head (x:_) =
+  x
+
+maybe x _ Nothing =
+  x
+maybe _ f (Some x) =
+  f
+    x
+
+fst (x,_) =
+  x
+
+fst' (# x,_ #) =
+  x
+
+fstPrism (# x | | #) =
+  Just
+    x
+fstPrism (# | _ | #) =
+  Nothing
+fstPrism (# | | _ #) =
+  Nothing
+
+empty [] =
+  True
+empty _ =
+  False
+
+unSum (Sum {getSum = s}) =
+  s
+
+mag2 Point {x
+           ,y} =
+  sqr
+    x + sqr
+          y
+mag2 Point {..} =
+  sqr
+    x + sqr
+          y
+
+strict !x =
+  x
+
+irrefutable ~x =
+  x
+
+(//) a b =
+  undefined
+
+a // b =
+  undefined
+
+main =
+  do greet
+       "World"
+  where greet who =
+          putStrLn $ "Hello, " ++ who ++ "!"
+```
+
+### ForImp and ForExp
+
+``` haskell
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+foreign import ccall sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall unsafe exit :: Double -> Double
+
+foreign export ccall Nothing callback :: Int -> Int
+```
+
+### Pragmas
+
+``` haskell
+{-# RULES
+ #-}
+
+{-# RULES
+"map/map" forall f g xs . map f (map g xs) = map (f . g) xs
+ #-}
+
+{-# RULES
+"map/append" [2] forall f xs ys . map f (xs ++ ys) =
+             map f xs ++ map f ys
+ #-}
+
+{-# DEPRECATED
+ #-}
+
+{-# DEPRECATED
+foo "use bar instead"
+ #-}
+
+{-# DEPRECATED
+foo, bar, baz "no longer supported"
+ #-}
+
+{-# WARNING
+ #-}
+
+{-# WARNING
+foo "use bar instead"
+ #-}
+
+{-# WARNING
+foo, bar, baz "no longer supported"
+ #-}
+
+{-# INLINE foo #-}
+
+{-# INLINE foo #-}
+
+{-# INLINE foo #-}
+
+{-# NOINLINE foo #-}
+
+{-# INLINE CONLIKE foo #-}
+
+{-# INLINE CONLIKE [3] foo #-}
+
+{-# SPECIALISE foo :: Int -> Int #-}
+
+{-# SPECIALISE [3] foo :: Int -> Int, Float -> Float #-}
+
+{-# SPECIALISE INLINE foo :: Int -> Int #-}
+
+{-# SPECIALISE NOINLINE foo :: Int -> Int #-}
+
+{-# SPECIALISE instance Foo Int #-}
+
+{-# SPECIALISE instance forall a . (Ord a) => Foo a #-}
+
+{-# ANN foo (Just "Foo") #-}
+
+{-# ANN type Foo (Just "Foo") #-}
+
+{-# ANN module (Just "Foo") #-}
+
+{-# MINIMAL foo | bar , (baz | quux) #-}
+```
+
+## Exp
+
+### Var, Con, Lit, Tuple, UnboxedSum, List, and ExpTypeSig
+
+``` haskell
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+
+foo =
+  foo
+
+foo =
+  Nothing
+
+foo =
+  123
+
+foo =
+  'x'
+
+foo =
+  ""
+
+foo =
+  "Lorem Ipsum Dolor Amet Sit"
+
+foo =
+  ()
+
+foo =
+  (1
+  ,2)
+
+foo =
+  (1 -- the one
+  ,2)
+
+foo =
+  (# #)
+
+foo =
+  (# 1
+    ,2 #)
+
+foo =
+  (# 1 -- the one
+    ,2 #)
+
+foo =
+  (# 1 #)
+
+foo =
+  (# | 1 | | #)
+
+foo =
+  (# | 1 -- the one
+                   | | #)
+
+foo =
+  []
+
+foo =
+  [1]
+
+foo =
+  [1
+  ,2]
+
+foo =
+  [1 -- the one
+  ,2]
+
+foo =
+  1 :: Int
+```
+
+### App, InfixApp, NegApp, LeftSection, RightSection
+
+``` haskell
+foo =
+  foldl
+    fn
+    init
+    list
+
+foo =
+  foldl
+    fn
+    init
+    list
+
+foo =
+  1 + 2
+
+foo =
+  fn `map` list
+
+foo =
+  -3
+
+foo =
+  (+ arg)
+
+foo =
+  (`op` arg)
+
+foo =
+  (arg +)
+
+foo =
+  (arg `op`)
+```
+
+### EnumFrom, EnumFromTo, EnumFromThen, EnumFromThenTo, ParArrayFromTo, ParArrayFromThenTo
+
+``` haskell
+foo =
+  [1 ..]
+
+foo =
+  [1 .. 10]
+
+foo =
+  [1,2 ..]
+
+foo =
+  [1,2 .. 10]
+
+foo =
+  [:1 .. 10:]
+
+foo =
+  [:1, 2 .. 10:]
+```
+
+### ListComp, ParComp, and ParArrayComp
+
+``` haskell
+{-# LANGUAGE TransformListComp #-}
+
+foo =
+  [(x
+   ,y)
+  |x <- xs
+  ,y <- ys]
+
+foo =
+  [(x
+   ,y) -- cartesian product
+  |x <- xs -- first list
+  ,y <- ys -- second list
+   ]
+
+foo =
+  [(x, y)| x <- xs| y <- ys]
+
+foo =
+  [(x, y)| x <- xs| y <- ys]
+
+foo =
+  [:(x, y)| x <- xs| y <- ys:]
+
+foo =
+  [:(x, y)| x <- xs| y <- ys:]
+
+foo =
+  [(x
+   ,y)
+  |x <- xs
+  ,y <- ys
+  ,then reverse
+  ,then sortWith by (x + y)
+  ,then group using permutations
+  ,then group by (x + y) using groupWith]
+```
+
+### RecConstr and RecUpdate
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+
+foo =
+  Point {x = 
+             1
+        ,y = 
+             2}
+
+foo =
+  Point {x = 
+             1 -- the one
+        ,y
+        ,..}
+
+foo =
+  bar {x = 
+           1}
+
+foo =
+  bar {x = 
+           1 -- the one
+      ,y
+      ,..}
+```
+
+### Let, If, MultiIf, and Case
+
+``` haskell
+{-# LANGUAGE MultiWayIf #-}
+
+foo =
+  let x =
+        x
+  in x
+
+foo =
+  let x =
+        x -- bottom
+  in 
+     -- bottom
+     x
+
+foo =
+  if null
+       xs
+     then None
+     else Some $ head
+                   xs
+
+foo =
+  if null
+       xs -- condition
+     then None -- it's empty
+     else Some $ head
+                   xs -- it's not
+
+foo =
+  if | null
+        xs ->
+       None
+     | otherwise ->
+       Some $ head
+                xs
+
+foo =
+  if | null
+        xs ->
+       -- it's empty
+       None
+     | otherwise ->
+       -- it's not
+       Some $ head
+                x
+
+foo =
+  case x of
+    True ->
+      False
+    False ->
+      True
+
+foo =
+  case xs of
+    [] ->
+      -- it's empty
+      None
+    x:_ ->
+      -- it's not
+      Some
+        x
+
+foo =
+  case xs of
+    _
+      | null
+         xs ->
+        None
+    _ ->
+      Some $ head
+               x
+```
+
+### Do and MDo
+
+``` haskell
+{-# LANGUAGE RecursiveDo #-}
+
+foo =
+  do return
+       ()
+
+foo =
+  do return
+       ()
+
+foo =
+  do this <- that
+     let this' =
+           tail
+             this
+     if this -- condition
+        then that
+        else those
+
+foo =
+  mdo return
+        ()
+```
+
+### Lambda, LCase
+
+``` haskell
+{-# LANGUAGE LambdaCase #-}
+
+foo =
+  \x -> 
+     x
+
+foo =
+  \ ~x -> 
+      x
+
+foo =
+  \ !x -> 
+      x
+
+foo d =
+  \case
+    Nothing ->
+      d
+    Some x ->
+      x
+```
+
+### BracketExp, SpliceExp, QuasiQuote, VarQuote, and TypQuote
+
+``` haskell
+{-# LANGUAGE TemplateHaskell #-}
+
+mkDecl :: Q Decl
+mkDecl =
+  [d| id x = x |]
+
+mkType :: Q Type
+mkType =
+  [t|(a,b) -> a|]
+
+mkPat :: Q Pat
+mkPat =
+  [p|(a,b)|]
+
+mkExp :: Q Exp
+mkExp =
+  [|a|]
+
+fst :: $(mkType)
+fst $(mkPat) =
+  $(mkExp)
+
+html =
+  [html|<p>Lorem Ipsum Dolor Amet Sit</p>|]
+
+foo =
+  mkSomething
+    'id
+    'Nothing
+    ''Maybe
+```
+
+# Regression Tests
+
+## Do
+
+Before comments and onside indent do not mix well.
+
+``` haskell
+foo =
+  do 
+     -- comment
+     some
+       expression
+```
+
+## Onside
+
+Indent within onside started on non-empty line should still not stack.
+
+``` haskell
+foo =
+  if cond
+     then do this
+     else do that
+```
+
+Before comments at the start of onside do not trigger onside.
+
+``` haskell
+foo =
+  do 
+     -- comment
+     some
+       expression
+```
+
+Matche arms have individual onside.
+
+``` haskell
+foo True =
+  some -- comment
+    expression
+foo False =
+  some -- comment
+    other
+    expression
+```
+
+Where binds are considered outside of onside.
+
+``` haskell
+foo =
+  some -- comment
+    expression
+  where expression =
+          other
+```
+
+Align overrides onside.
+
+``` haskell
+foo =
+  some
+    expr
+    [1 -- comment
+    ,2]
+```
+
+If-then-else must always indent in do blocks.
+
+``` haskell
+foo =
+  do if condition -- comment
+        then this
+        else that
+```
diff --git a/styles/gibiansky.md b/styles/gibiansky.md
new file mode 100644
--- /dev/null
+++ b/styles/gibiansky.md
@@ -0,0 +1,997 @@
+# Introduction
+
+This file acts both as a presentation of the Floskell formatting
+styles, as well as a set of regression tests.
+
+You can see how a particular style will format Haskell source by
+reading the matching Markdown file in the styles/ directory.
+
+For regression testing, the canonical source, TEST.md in the root
+directory, is parsed and each Haskell code block formatted according
+to all predefined styles.  The formatted output is then compared with
+the corresponding, already formatted code block in the <style\>.md file
+in the styles/ subdirectory.
+
+The regression test will also verify that repeated invocations of the
+pretty printer will not modify an already formatted piece of code.
+
+The following code block acts as a quick presentation for the
+different formatting styles, by presenting a mixture of common Haskell
+constructs.
+
+``` haskell
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+{- |
+Module: Style.Haskell.Example
+
+Haskell Code Style Example.
+-}
+module Style.Haskell.Example
+    ( -- * Types
+      Enum(..)
+    , Either(..)
+    , Point(..)
+      -- * Functions
+    , hello) where
+
+-- Module imports
+import qualified Control.Monad.Trans.State (State, evalState, execState, get
+                                          , modify, put, runState)
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import           Prelude hiding (map)
+
+-- Data declarations
+data Enum = CaseA
+          | CaseB
+          | CaseC
+  deriving (Eq, Enum, Show)
+
+data Either a b = Left a
+                | Right b
+  deriving (Eq, Show)
+
+data Point = Point { pointX :: Float, pointY :: Float, pointLabel :: String }
+  deriving (Eq, Show)
+
+-- Type classes
+class Functor f => Applicative a where
+  pure :: b -> a b
+  ap :: a (b -> c) -> a b -> a c
+
+class Fundep a b | a -> b where
+  convert :: a -> b
+
+instance Functor f => Functor (Wrap f) where
+  fmap f (Wrap x) = Wrap $ fmap f x
+
+-- Values
+origin :: Point
+origin = Point { pointX = 0, pointY = 0, pointLabel = "Origin" }
+
+lorem :: [String]
+lorem =
+  [ "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+  , "Curabitur nec ante nec mauris ornare suscipit."
+  , "In ac vulputate libero."
+  , "Duis eget magna non purus imperdiet molestie nec quis mauris."
+  , "Praesent blandit quam vel arcu pellentesque, id aliquet turpis faucibus."]
+
+-- Functions
+facs :: [Int]
+facs = [1, 1] ++ zipWith (+) (tailfacs)
+
+hello :: MonadIO m => m ()
+hello = do
+  name <- liftIO getLine
+  liftIO . putStrLn $ greetings name
+  where
+    greetings n = "Hello " ++ n ++ "!"
+
+letExpr :: Point -> String
+letExp x = let y = 1
+               z = 2
+           in if x > 0
+              then y
+              else z
+
+ifExpr :: Bool -> Bool
+ifExpr b = if b == True
+           then False
+           else True
+
+caseExpr :: [a] -> Maybe a
+caseExpr xs = case xs of
+  []    -> Nothing
+  (x:_) -> Just x
+
+guarded :: Int -> Int
+guarded x
+  | x == 0 = 1
+  | x == 1 = 1
+  | otherwise = guarded (x - 2) + guarded (x - 1)
+
+someLongFunctionNameWithALotOfParameters
+  :: (MonadIO m, MonadRandom m) => String -> (String -> String) -> m ()
+someLongFunctionNameWithALotOfParameters = undefined
+```
+
+# Unit Tests
+
+## ModuleHead and ExportSpecList
+
+Without exports
+
+``` haskell
+module Main where
+```
+
+With exports
+
+``` haskell
+module Main (foo, bar, baz, main) where
+```
+
+With exports and comments
+
+``` haskell
+module Main
+    ( -- * Main Program
+      main
+      -- * Functions
+    , foo -- foo function
+    , bar -- bar function
+    , baz -- baz function
+    ) where
+```
+
+With deprecation
+
+``` haskell
+module Main {-# DEPRECATED "no longer supported" #-} where
+```
+
+With warnings
+
+``` haskell
+module Main {-# WARNING "do not use" #-} where
+```
+
+## ImportDecl
+
+``` haskell
+import           Prelude
+import           Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.ByteString (ByteString, pack, unpack)
+import qualified Data.ByteString as BS (pack, unpack)
+import           Control.Monad hiding (forM)
+import {-# SOURCE #-} safe qualified "foo" Foo as F
+```
+
+## Decl
+
+### TypeDecl
+
+``` haskell
+type Name = String
+
+type Pair a = (a, a)
+
+type Fun a b = a -> b
+```
+
+### DataDecl and GDataDecl
+
+``` haskell
+data Void
+
+data Unit = Unit
+
+data Maybe a = Nothing
+             | Just a
+
+data Num a => SomeNum = SomeNum a
+
+newtype RWS r w s = RWS (ReaderT r (WriterT w (StateT s Identity)))
+  deriving (Functor, Applicative, Monad)
+
+data Enum = One   -- Foo
+          | Two   -- Bar
+          | Three -- Baz
+
+data Foo
+  deriving ()
+
+data Foo
+  deriving Show
+
+data Foo
+  deriving (Show)
+
+data Foo
+  deriving (Eq, Ord)
+
+data Expr :: * -> * where
+  Const :: Int -> Expr Int
+  Plus :: Expr Int -> Expr Int -> Expr Int
+  Eq :: Expr Int -> Expr Int -> Expr Bool
+  deriving (Show)
+
+data Term a where
+  Lit :: { val :: Int } -> Term Int
+  Succ :: { num :: Term Int } -> Term Int
+  Pred :: { num :: Term Int } -> Term Int
+  IsZero :: { arg :: Term Int } -> Term Bool
+  Pair :: { arg1 :: Term a, arg2 :: Term b } -> Term (a, b)
+  If :: { cnd :: Term Bool, tru :: Term a, fls :: Term a } -> Term a
+```
+
+### TypeFamDecl, TypeInsDecl, and ClosedTypeFamDecl
+
+``` haskell
+type family Mutable v
+
+type family Mutable v = (r :: *)
+
+type family Mutable v = r | r -> v
+
+type instance Mutable Int = MIntVector
+
+type family Store a where
+  Store Bool = [Int]
+  Store a = [a]
+
+type family Store a = (r :: *) where
+  Store a = [a]
+
+type family Store a = r | r -> a where
+  Store a = [a]
+```
+
+### DataFamDecl, DataInsDecl, and GDataInsDecl
+
+``` haskell
+data family List a
+
+data instance List () = NilList Int
+
+data instance List Char = CharNil
+                        | CharCons Char (List Char)
+  deriving (Eq, Ord, Show)
+
+data instance List Int :: * where
+  IntNil :: List Int
+  IntCons :: Int -> List Int
+  deriving (Eq, Ord, Show)
+
+data instance List Int :: * where
+  IntNil :: List Int
+  IntCons :: { val :: Int } -> List Int
+  deriving (Eq, Ord, Show)
+
+newtype Penalty = Penalty Int
+  deriving (Eq, Ord)
+  deriving stock (Read, Show)
+  deriving newtype (Num)
+  deriving anyclass (FromJSON, ToJSON)
+  deriving (Semigroup, Monoid) via M.Sum Int
+```
+
+### ClassDecl and InstDecl
+
+``` haskell
+class Monoid a where
+  mempty :: a
+  mappend :: a -> a -> a
+
+class Applicative m => Monad m where
+  fail :: m a
+  return :: a -> m a
+  (>>=) :: a -> (a -> m b) -> m b
+
+class Monad m => MonadState s m | m -> s where
+  get :: m s
+  put :: s -> m ()
+  state :: (s -> (a, s)) -> m a
+
+class ToJSON a where
+  toJSON :: a -> Value
+  default toJSON :: (Generic a, GToJSON (Rep a)) => a -> Value
+  toJSON = genericToJSON defaultOptions
+
+instance ToJSON ()
+
+instance Bounded Bool where
+  minBound = False
+
+  maxBound = True
+
+instance Semigroup a => Monoid (Maybe a) where
+  mempty = Nothing
+
+  Nothing `mappend` m = m
+  m `mappend` Nothing = m
+  Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
+
+instance Data () where
+  type Base = ()
+
+  newtype Wrapped = Wrapped { unWrap :: () }
+
+  data Expr :: * -> * where
+    Const :: Int -> Expr Int
+    Plus :: Expr Int -> Expr Int -> Expr Int
+    Eq :: Expr Int -> Expr Int -> Expr Bool
+```
+
+### DerivDecl
+
+``` haskell
+deriving instance Eq a => Eq (Sum a)
+
+deriving instance {-# OVERLAP #-} Eq a => Eq (Sum a)
+
+deriving stock instance {-# OVERLAPS #-} Eq a => Eq (Sum a)
+
+deriving anyclass instance {-# OVERLAPPING #-} Eq a => Eq (Sum a)
+
+deriving newtype instance {-# OVERLAPPABLE #-} Eq a => Eq (Sum a)
+```
+
+### InfixDecl
+
+``` haskell
+infix 4 ==, /=, <, <=, >, >=
+
+infixr 0 $
+
+infixl !!
+```
+
+### DefaultDecl
+
+``` haskell
+default ()
+
+default (Integer, Double)
+```
+
+### SpliceDecl
+
+``` haskell
+$foo
+
+$(bar baz)
+```
+
+### TypeSig
+
+``` haskell
+id :: a -> a
+sort :: Ord a => [a] -> [a]
+long :: (IsString a, Monad m)
+     => ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> a
+     -> m ()
+mktime :: Int -- hours
+       -> Int -- minutes
+       -> Int -- seconds
+       -> Time
+transform :: forall a. St -> State St a -> EitherT ServantErr IO a
+```
+
+### PatSyn and PatSynSig
+
+``` haskell
+{-# LANGUAGE PatternSynonyms #-}
+
+pattern MyJust :: a -> Maybe a
+pattern MyJust a = Just a
+
+pattern MyPoint :: Int -> Int -> (Int, Int)
+pattern MyPoint { x, y } = (x, y)
+
+pattern ErrorCall :: String -> ErrorCall
+pattern ErrorCall s <- ErrorCallWithLocation s _
+  where
+    ErrorCall s = ErrorCallWithLocation s ""
+
+pattern IsTrue :: Show a => a
+pattern IsTrue <- ((== "True") . show -> True)
+
+pattern ExNumPat :: () => Show b => b -> T
+pattern ExNumPat x = MkT x
+
+pattern Foo, Bar :: Show a => a
+```
+
+### FunBind and PatBind
+
+``` haskell
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE RecordWildCards #-}
+
+pi = 3.14
+
+id x = x
+
+not False = True
+not _ = False
+
+head (x:_) = x
+
+maybe x _ Nothing = x
+maybe _ f (Some x) = f x
+
+fst (x, _) = x
+
+fst' (# x, _ #) = x
+
+fstPrism (# x | | #) = Just x
+fstPrism (# | _ | #) = Nothing
+fstPrism (# | | _ #) = Nothing
+
+empty [] = True
+empty _ = False
+
+unSum (Sum { getSum = s }) = s
+
+mag2 Point { x, y } = sqr x + sqr y
+mag2 Point { .. } = sqr x + sqr y
+
+strict !x = x
+
+irrefutable ~x = x
+
+(//) a b = undefined
+
+a // b = undefined
+
+main = do
+  greet "World"
+  where
+    greet who = putStrLn $ "Hello, " ++ who ++ "!"
+```
+
+### ForImp and ForExp
+
+``` haskell
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+foreign import ccall sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall unsafe exit :: Double -> Double
+
+foreign export ccall callback :: Int -> Int
+```
+
+### Pragmas
+
+``` haskell
+{-# RULES #-}
+
+{-# RULES "map/map" forall f g xs. map f (map g xs) = map (f . g) xs #-}
+
+{-# RULES "map/append" [2] forall f xs ys. map f (xs ++ ys) =
+          map f xs ++ map f ys #-}
+
+{-# DEPRECATED #-}
+{-# DEPRECATED foo "use bar instead" #-}
+{-# DEPRECATED foo, bar, baz "no longer supported" #-}
+{-# WARNING #-}
+{-# WARNING foo "use bar instead" #-}
+{-# WARNING foo, bar, baz "no longer supported" #-}
+{-# INLINE foo #-}
+{-# INLINE [3] foo #-}
+{-# INLINE [~3] foo #-}
+{-# NOINLINE foo #-}
+{-# INLINE CONLIKE foo #-}
+{-# INLINE CONLIKE [3] foo #-}
+{-# SPECIALISE foo :: Int -> Int #-}
+{-# SPECIALISE [3] foo :: Int -> Int, Float -> Float #-}
+{-# SPECIALISE INLINE foo :: Int -> Int #-}
+{-# SPECIALISE NOINLINE foo :: Int -> Int #-}
+{-# SPECIALISE instance Foo Int #-}
+{-# SPECIALISE instance forall a. (Ord a) => Foo a #-}
+{-# ANN foo (Just "Foo") #-}
+{-# ANN type Foo (Just "Foo") #-}
+{-# ANN module (Just "Foo") #-}
+{-# MINIMAL foo | bar, (baz | quux) #-}
+```
+
+## Exp
+
+### Var, Con, Lit, Tuple, UnboxedSum, List, and ExpTypeSig
+
+``` haskell
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+
+foo = foo
+
+foo = Nothing
+
+foo = 123
+
+foo = 'x'
+
+foo = ""
+
+foo = "Lorem Ipsum Dolor Amet Sit"
+
+foo = ()
+
+foo = (1, 2)
+
+foo = ( 1 -- the one
+      , 2)
+
+foo = (1, )
+
+foo = (, 2)
+
+foo = (, 2, )
+
+foo = (# #)
+
+foo = (# 1, 2 #)
+
+foo = (# 1 -- the one
+       , 2 #)
+
+foo = (# 1 #)
+
+foo = (# | 1 | | #)
+
+foo = (# | 1 -- the one
+      | | #)
+
+foo = []
+
+foo = [1]
+
+foo = [1, 2]
+
+foo = [ 1 -- the one
+      , 2]
+
+foo = 1 :: Int
+```
+
+### App, InfixApp, NegApp, LeftSection, RightSection
+
+``` haskell
+foo = foldl fn init list
+
+foo = foldl
+  fn -- reducer
+  init -- initial value
+  list
+
+foo = 1 + 2
+
+foo = fn `map` list
+
+foo = -3
+
+foo = (+ arg)
+
+foo = (`op` arg)
+
+foo = (arg +)
+
+foo = (arg `op`)
+```
+
+### EnumFrom, EnumFromTo, EnumFromThen, EnumFromThenTo, ParArrayFromTo, ParArrayFromThenTo
+
+``` haskell
+foo = [1 ..]
+
+foo = [1 .. 10]
+
+foo = [1, 2 ..]
+
+foo = [1, 2 .. 10]
+
+foo = [:1 .. 10:]
+
+foo = [:1, 2 .. 10:]
+```
+
+### ListComp, ParComp, and ParArrayComp
+
+``` haskell
+{-# LANGUAGE TransformListComp #-}
+
+foo = [(x, y) | x <- xs, y <- ys]
+
+foo = [(x, y) -- cartesian product
+      | x <- xs -- first list
+      , y <- ys -- second list
+      ]
+
+foo = [(x, y) | x <- xs | y <- ys]
+
+foo = [(x, y) -- zip
+      | x <- xs -- first list
+      | y <- ys -- second list
+      ]
+
+foo = [:(x, y) | x <- xs | y <- ys:]
+
+foo = [:(x, y) -- zip
+      | x <- xs -- first list
+      | y <- ys -- second list
+      :]
+
+foo = [(x, y)
+      | x <- xs
+      , y <- ys
+      , then reverse
+      , then sortWith by (x + y)
+      , then group using permutations
+      , then group by (x + y) using groupWith]
+```
+
+### RecConstr and RecUpdate
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+
+foo = Point { x = 1, y = 2 }
+
+foo = Point { x = 1 -- the one
+            , y
+            , ..
+            }
+
+foo = bar { x = 1 }
+
+foo = bar { x = 1 -- the one
+          , y
+          , ..
+          }
+```
+
+### Let, If, MultiIf, and Case
+
+``` haskell
+{-# LANGUAGE MultiWayIf #-}
+
+foo = let x = x
+      in x
+
+foo = let x = x -- bottom
+      in
+         -- bottom
+         x
+
+foo = if null xs
+      then None
+      else Some $ head xs
+
+foo = if null xs -- condition
+      then None -- it's empty
+      else Some $ head xs -- it's not
+
+foo = if
+  | null xs -> None
+  | otherwise -> Some $ head xs
+
+foo = if
+  | null xs ->
+    -- it's empty
+    None
+  | otherwise ->
+    -- it's not
+    Some $ head x
+
+foo = case x of
+  True  -> False
+  False -> True
+
+foo = case xs of
+  []  ->
+    -- it's empty
+    None
+  x:_ ->
+    -- it's not
+    Some x
+
+foo = case xs of
+  _
+    | null xs -> None
+  _ -> Some $ head x
+```
+
+### Do and MDo
+
+``` haskell
+{-# LANGUAGE RecursiveDo #-}
+
+foo = do
+  return ()
+
+foo = do
+  return ()
+
+foo = do
+  this <- that
+  let this' = tail this
+  if this -- condition
+    then that
+    else those
+
+foo = mdo
+  return ()
+```
+
+### Lambda, LCase
+
+``` haskell
+{-# LANGUAGE LambdaCase #-}
+
+foo = \x -> x
+
+foo = \ ~x -> x
+
+foo = \ !x -> x
+
+foo d = \case
+  Nothing -> d
+  Some x  -> x
+```
+
+### BracketExp, SpliceExp, QuasiQuote, VarQuote, and TypQuote
+
+``` haskell
+{-# LANGUAGE TemplateHaskell #-}
+
+mkDecl :: Q Decl
+mkDecl = [d|id x = x|]
+
+mkType :: Q Type
+mkType = [t|(a, b) -> a|]
+
+mkPat :: Q Pat
+mkPat = [p|(a, b)|]
+
+mkExp :: Q Exp
+mkExp = [|a|]
+
+fst :: $(mkType)
+fst $(mkPat) = $(mkExp)
+
+html = [html|<p>Lorem Ipsum Dolor Amet Sit</p>|]
+
+foo = mkSomething 'id 'Nothing ''Maybe
+```
+
+# Regression Tests
+
+## Do
+
+Before comments and onside indent do not mix well.
+
+``` haskell
+foo = do
+  -- comment
+  some expression
+```
+
+## Types
+
+Long types allow linebreaks.
+
+``` haskell
+newtype MyMonadT a b m =
+  MyMonad { runMyMonad
+              :: StateT
+                ([(a, a -> b)])
+                (ReaderT a (ExceptT [IM.IntMap b]) (WriterT [IS.IntSet x] m))
+          }
+```
+
+Promoted types.
+
+``` haskell
+type Foo = Bar 1 "foo" '() '(A, B) '[X, Y]
+```
+
+## Patterns
+
+Long function pattern matches allow linebreaks.
+
+``` haskell
+doThing
+  (Constructor field1 field2 field3)
+  (Constructor field1 field2 field3)
+  (Constructor field1 field2 field3) = undefined
+```
+
+## Onside
+
+Indent within onside started on non-empty line should still not stack.
+
+``` haskell
+foo = if cond
+      then do
+        this
+      else do
+        that
+```
+
+Before comments at the start of onside do not trigger onside.
+
+``` haskell
+foo = do
+  -- comment
+  some expression
+```
+
+Matche arms have individual onside.
+
+``` haskell
+foo True = some -- comment
+  expression
+foo False = some -- comment
+  other
+  expression
+```
+
+Where binds are considered outside of onside.
+
+``` haskell
+foo = some -- comment
+  expression
+  where
+    expression = other
+```
+
+Align overrides onside.
+
+``` haskell
+foo = some
+  expr
+  [ 1 -- comment
+  , 2]
+```
+
+If-then-else must always indent in do blocks.
+
+``` haskell
+foo = do
+  if condition -- comment
+    then this
+    else that
+```
+
+Lists must not suppress onside.
+
+``` haskell
+foo = case x of
+  [ y -- comment
+    , z] -> bar
+
+foo = do
+  [ x -- comment
+    , y]
+```
+
+## Comments
+
+Don't be too eager in assigning comments to the following AST node.
+
+``` haskell
+data Foo =
+  Foo { fooBar :: Text
+        -- ^A comment, long enough to end up on its own line, or at least I hope so.
+      }
+  deriving (Eq)
+```
+
+Keep comments together and aligned.
+
+``` haskell
+-- block
+-- one
+data Foo = Foo  -- some
+                -- comments
+         | Quux -- more
+                -- comments
+-- block
+-- two
+```
+
+... even when haskell-src-exts has weird column span info.
+
+``` haskell
+module Main where
+
+-- comment
+instance Foo Bar where
+  foo = undefined
+
+bar = undefined
+```
+
+Only comments.
+
+``` haskell
+-- some comment
+```
+
+Make sure no comments are dropped from operators or argument.
+
+``` haskell
+foo = some -- comment 1
+  -- comment 2
+  %~ -- comment 3
+  argument -- comment 4
+```
+
+Comments after `where` stay there.
+
+``` haskell
+consM :: Monad m => m a -> Stream m a -> Stream m a
+consM m (Stream step state) = Stream step1 Nothing
+  where
+    {-# INLINE_LATE step1 #-}
+    step1 _ _ = undefined
+```
+
+Comments between declarations do not cause empty lines.
+
+``` haskell
+f :: ()
+--
+f = ()
+```
+
+## Indentation and Line Prefixes
+
+Preserving indentation and line prefixes so that Floskell can be run
+on individual declarations and quoted haskell code.
+
+``` haskell
+    data Enum = One   -- Foo
+              | Two   -- Bar
+              | Three -- Baz
+```
+
+``` haskell
+>
+>    data Enum = One   -- Foo
+>              | Two   -- Bar
+>              | Three -- Baz
+>
+```
+
+## Module Exports
+
+Long module exports don't force overlong line.
+
+``` haskell
+module SimpleFunctions
+    ( identity
+    , compose
+    , append
+    , firstElement
+    , secondElem) where
+```
diff --git a/styles/johan-tibell.md b/styles/johan-tibell.md
new file mode 100644
--- /dev/null
+++ b/styles/johan-tibell.md
@@ -0,0 +1,1058 @@
+# Introduction
+
+This file acts both as a presentation of the Floskell formatting
+styles, as well as a set of regression tests.
+
+You can see how a particular style will format Haskell source by
+reading the matching Markdown file in the styles/ directory.
+
+For regression testing, the canonical source, TEST.md in the root
+directory, is parsed and each Haskell code block formatted according
+to all predefined styles.  The formatted output is then compared with
+the corresponding, already formatted code block in the <style\>.md file
+in the styles/ subdirectory.
+
+The regression test will also verify that repeated invocations of the
+pretty printer will not modify an already formatted piece of code.
+
+The following code block acts as a quick presentation for the
+different formatting styles, by presenting a mixture of common Haskell
+constructs.
+
+``` haskell
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+{- |
+Module: Style.Haskell.Example
+
+Haskell Code Style Example.
+-}
+module Style.Haskell.Example
+  (-- * Types
+   Enum(..)
+  ,Either(..)
+  ,Point(..)
+   -- * Functions
+  ,hello) where
+
+-- Module imports
+import qualified Control.Monad.Trans.State
+       (State,evalState,execState,get,modify,put,runState)
+import qualified Data.Map as Map
+import qualified Data.Text as Text
+import Prelude hiding (map)
+
+-- Data declarations
+data Enum
+    = CaseA
+    | CaseB
+    | CaseC
+    deriving (Eq,Enum,Show)
+
+data Either a b
+    = Left a
+    | Right b
+    deriving (Eq,Show)
+
+data Point =
+    Point
+    { pointX :: Float
+    , pointY :: Float
+    , pointLabel :: String
+    }
+    deriving (Eq,Show)
+
+-- Type classes
+class Functor f => Applicative a where
+    pure :: b -> a b
+    ap :: a (b -> c) -> a b -> a c
+
+class Fundep a b | a -> b where
+    convert :: a -> b
+
+instance Functor f => Functor (Wrap f) where
+    fmap f (Wrap x) = Wrap $ fmap f x
+
+-- Values
+origin :: Point
+origin =
+    Point
+    { pointX = 0
+    , pointY = 0
+    , pointLabel = "Origin"
+    }
+
+lorem :: [String]
+lorem =
+    [ "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+    , "Curabitur nec ante nec mauris ornare suscipit."
+    , "In ac vulputate libero."
+    , "Duis eget magna non purus imperdiet molestie nec quis mauris."
+    , "Praesent blandit quam vel arcu pellentesque, id aliquet turpis faucibus."]
+
+-- Functions
+facs :: [Int]
+facs = [1, 1] ++ zipWith (+) (tailfacs)
+
+hello :: MonadIO m => m ()
+hello = do
+    name <- liftIO getLine
+    liftIO . putStrLn $ greetings name
+  where
+    greetings n = "Hello " ++ n ++ "!"
+
+letExpr :: Point -> String
+letExp x =
+    let y = 1
+        z = 2
+    in if x > 0
+           then y
+           else z
+
+ifExpr :: Bool -> Bool
+ifExpr b =
+    if b == True
+        then False
+        else True
+
+caseExpr :: [a] -> Maybe a
+caseExpr xs = case xs of
+    [] -> Nothing
+    (x:_) -> Just x
+
+guarded :: Int -> Int
+guarded x
+  | x == 0 = 1
+  | x == 1 = 1
+  | otherwise = guarded (x - 2) + guarded (x - 1)
+
+someLongFunctionNameWithALotOfParameters
+    :: (MonadIO m, MonadRandom m) => String -> (String -> String) -> m ()
+someLongFunctionNameWithALotOfParameters = undefined
+```
+
+# Unit Tests
+
+## ModuleHead and ExportSpecList
+
+Without exports
+
+``` haskell
+module Main where
+```
+
+With exports
+
+``` haskell
+module Main (foo,bar,baz,main) where
+```
+
+With exports and comments
+
+``` haskell
+module Main
+  (-- * Main Program
+   main
+   -- * Functions
+  ,foo -- foo function
+  ,bar -- bar function
+  ,baz -- baz function
+  ) where
+```
+
+With deprecation
+
+``` haskell
+module Main {-# DEPRECATED "no longer supported" #-} where
+```
+
+With warnings
+
+``` haskell
+module Main {-# WARNING "do not use" #-} where
+```
+
+## ImportDecl
+
+``` haskell
+import Prelude
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.ByteString (ByteString,pack,unpack)
+import qualified Data.ByteString as BS (pack,unpack)
+import Control.Monad hiding (forM)
+import {-# SOURCE #-} safe qualified "foo" Foo as F
+```
+
+## Decl
+
+### TypeDecl
+
+``` haskell
+type Name = String
+
+type Pair a = (a, a)
+
+type Fun a b = a -> b
+```
+
+### DataDecl and GDataDecl
+
+``` haskell
+data Void
+
+data Unit = Unit
+
+data Maybe a
+    = Nothing
+    | Just a
+
+data Num a => SomeNum = SomeNum a
+
+newtype RWS r w s = RWS (ReaderT r (WriterT w (StateT s Identity)))
+    deriving (Functor,Applicative,Monad)
+
+data Enum
+    = One   -- Foo
+    | Two   -- Bar
+    | Three -- Baz
+
+data Foo
+    deriving ()
+
+data Foo
+    deriving Show
+
+data Foo
+    deriving (Show)
+
+data Foo
+    deriving (Eq,Ord)
+
+data Expr :: * -> * where
+    Const :: Int -> Expr Int
+    Plus :: Expr Int -> Expr Int -> Expr Int
+    Eq :: Expr Int -> Expr Int -> Expr Bool
+    deriving (Show)
+
+data Term a where
+    Lit :: { val :: Int
+           } -> Term Int
+    Succ :: { num :: Term Int
+            } -> Term Int
+    Pred :: { num :: Term Int
+            } -> Term Int
+    IsZero :: { arg :: Term Int
+              } -> Term Bool
+    Pair :: { arg1 :: Term a
+            , arg2 :: Term b
+            } -> Term (a, b)
+    If :: { cnd :: Term Bool
+          , tru :: Term a
+          , fls :: Term a
+          } -> Term a
+```
+
+### TypeFamDecl, TypeInsDecl, and ClosedTypeFamDecl
+
+``` haskell
+type family Mutable v
+
+type family Mutable v = (r :: *)
+
+type family Mutable v = r | r -> v
+
+type instance Mutable Int = MIntVector
+
+type family Store a where
+    Store Bool = [Int]
+    Store a = [a]
+
+type family Store a = (r :: *) where
+    Store a = [a]
+
+type family Store a = r | r -> a where
+    Store a = [a]
+```
+
+### DataFamDecl, DataInsDecl, and GDataInsDecl
+
+``` haskell
+data family List a
+
+data instance List () = NilList Int
+
+data instance List Char
+    = CharNil
+    | CharCons Char (List Char)
+    deriving (Eq,Ord,Show)
+
+data instance List Int :: * where
+    IntNil :: List Int
+    IntCons :: Int -> List Int
+    deriving (Eq,Ord,Show)
+
+data instance List Int :: * where
+    IntNil :: List Int
+    IntCons :: { val :: Int
+               } -> List Int
+    deriving (Eq,Ord,Show)
+
+newtype Penalty = Penalty Int
+    deriving (Eq,Ord)
+    deriving stock (Read,Show)
+    deriving newtype (Num)
+    deriving anyclass (FromJSON,ToJSON)
+    deriving (Semigroup,Monoid) via M.Sum Int
+```
+
+### ClassDecl and InstDecl
+
+``` haskell
+class Monoid a where
+    mempty :: a
+    mappend :: a -> a -> a
+
+class Applicative m => Monad m where
+    fail :: m a
+    return :: a -> m a
+    (>>=) :: a -> (a -> m b) -> m b
+
+class Monad m => MonadState s m | m -> s where
+    get :: m s
+    put :: s -> m ()
+    state :: (s -> (a, s)) -> m a
+
+class ToJSON a where
+    toJSON :: a -> Value
+    default toJSON :: (Generic a, GToJSON (Rep a)) => a -> Value
+    toJSON = genericToJSON defaultOptions
+
+instance ToJSON ()
+
+instance Bounded Bool where
+    minBound = False
+
+    maxBound = True
+
+instance Semigroup a => Monoid (Maybe a) where
+    mempty = Nothing
+
+    Nothing `mappend` m = m
+    m `mappend` Nothing = m
+    Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)
+
+instance Data () where
+    type Base = ()
+
+    newtype Wrapped =
+        Wrapped
+        { unWrap :: ()
+        }
+
+    data Expr :: * -> * where
+        Const :: Int -> Expr Int
+        Plus :: Expr Int -> Expr Int -> Expr Int
+        Eq :: Expr Int -> Expr Int -> Expr Bool
+```
+
+### DerivDecl
+
+``` haskell
+deriving instance Eq a => Eq (Sum a)
+
+deriving instance {-# OVERLAP #-} Eq a => Eq (Sum a)
+
+deriving stock instance {-# OVERLAPS #-} Eq a => Eq (Sum a)
+
+deriving anyclass instance {-# OVERLAPPING #-} Eq a => Eq (Sum a)
+
+deriving newtype instance {-# OVERLAPPABLE #-} Eq a => Eq (Sum a)
+```
+
+### InfixDecl
+
+``` haskell
+infix 4 ==, /=, <, <=, >, >=
+
+infixr 0 $
+
+infixl !!
+```
+
+### DefaultDecl
+
+``` haskell
+default ()
+
+default (Integer,Double)
+```
+
+### SpliceDecl
+
+``` haskell
+$foo
+
+$(bar baz)
+```
+
+### TypeSig
+
+``` haskell
+id :: a -> a
+sort :: Ord a => [a] -> [a]
+long :: (IsString a, Monad m)
+     => ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> ByteString
+     -> a
+     -> m ()
+mktime :: Int -- hours
+       -> Int -- minutes
+       -> Int -- seconds
+       -> Time
+transform :: forall a. St -> State St a -> EitherT ServantErr IO a
+```
+
+### PatSyn and PatSynSig
+
+``` haskell
+{-# LANGUAGE PatternSynonyms #-}
+
+pattern MyJust :: a -> Maybe a
+pattern MyJust a = Just a
+
+pattern MyPoint :: Int -> Int -> (Int, Int)
+pattern MyPoint {x,y} = (x,y)
+
+pattern ErrorCall :: String -> ErrorCall
+pattern ErrorCall s <- ErrorCallWithLocation s _
+  where
+    ErrorCall s = ErrorCallWithLocation s ""
+
+pattern IsTrue :: Show a => a
+pattern IsTrue <- ((== "True") . show -> True)
+
+pattern ExNumPat :: () => Show b => b -> T
+pattern ExNumPat x = MkT x
+
+pattern Foo, Bar :: Show a => a
+```
+
+### FunBind and PatBind
+
+``` haskell
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+{-# LANGUAGE RecordWildCards #-}
+
+pi = 3.14
+
+id x = x
+
+not False = True
+not _ = False
+
+head (x:_) = x
+
+maybe x _ Nothing = x
+maybe _ f (Some x) = f x
+
+fst (x,_) = x
+
+fst' (# x,_ #) = x
+
+fstPrism (# x | | #) = Just x
+fstPrism (# | _ | #) = Nothing
+fstPrism (# | | _ #) = Nothing
+
+empty [] = True
+empty _ = False
+
+unSum (Sum {getSum = s}) = s
+
+mag2 Point {x,y} = sqr x + sqr y
+mag2 Point {..} = sqr x + sqr y
+
+strict !x = x
+
+irrefutable ~x = x
+
+(//) a b = undefined
+
+a // b = undefined
+
+main = do
+    greet "World"
+  where
+    greet who = putStrLn $ "Hello, " ++ who ++ "!"
+```
+
+### ForImp and ForExp
+
+``` haskell
+{-# LANGUAGE ForeignFunctionInterface #-}
+
+foreign import ccall sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall "sin" sin :: Double -> Double
+
+foreign import ccall unsafe exit :: Double -> Double
+
+foreign export ccall callback :: Int -> Int
+```
+
+### Pragmas
+
+``` haskell
+{-# RULES #-}
+
+{-# RULES "map/map" forall f g xs. map f (map g xs) = map (f . g) xs #-}
+
+{-# RULES "map/append" [2] forall f xs ys. map f (xs ++ ys) =
+          map f xs ++ map f ys #-}
+
+{-# DEPRECATED #-}
+{-# DEPRECATED foo "use bar instead" #-}
+{-# DEPRECATED foo, bar, baz "no longer supported" #-}
+{-# WARNING #-}
+{-# WARNING foo "use bar instead" #-}
+{-# WARNING foo, bar, baz "no longer supported" #-}
+{-# INLINE foo #-}
+{-# INLINE [3] foo #-}
+{-# INLINE [~3] foo #-}
+{-# NOINLINE foo #-}
+{-# INLINE CONLIKE foo #-}
+{-# INLINE CONLIKE [3] foo #-}
+{-# SPECIALISE foo :: Int -> Int #-}
+{-# SPECIALISE [3] foo :: Int -> Int, Float -> Float #-}
+{-# SPECIALISE INLINE foo :: Int -> Int #-}
+{-# SPECIALISE NOINLINE foo :: Int -> Int #-}
+{-# SPECIALISE instance Foo Int #-}
+{-# SPECIALISE instance forall a. (Ord a) => Foo a #-}
+{-# ANN foo (Just "Foo") #-}
+{-# ANN type Foo (Just "Foo") #-}
+{-# ANN module (Just "Foo") #-}
+{-# MINIMAL foo | bar, (baz | quux) #-}
+```
+
+## Exp
+
+### Var, Con, Lit, Tuple, UnboxedSum, List, and ExpTypeSig
+
+``` haskell
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE UnboxedSums #-}
+
+foo = foo
+
+foo = Nothing
+
+foo = 123
+
+foo = 'x'
+
+foo = ""
+
+foo = "Lorem Ipsum Dolor Amet Sit"
+
+foo = ()
+
+foo = (1, 2)
+
+foo =
+    ( 1 -- the one
+    , 2)
+
+foo = (1, )
+
+foo = (, 2)
+
+foo = (, 2, )
+
+foo = (# #)
+
+foo = (# 1, 2 #)
+
+foo =
+    (# 1 -- the one
+     , 2 #)
+
+foo = (# 1 #)
+
+foo = (# | 1 | | #)
+
+foo =
+    (# | 1 -- the one
+    | | #)
+
+foo = []
+
+foo = [1]
+
+foo = [1, 2]
+
+foo =
+    [ 1 -- the one
+    , 2]
+
+foo = 1 :: Int
+```
+
+### App, InfixApp, NegApp, LeftSection, RightSection
+
+``` haskell
+foo = foldl fn init list
+
+foo =
+    foldl
+        fn -- reducer
+        init -- initial value
+        list
+
+foo = 1 + 2
+
+foo = fn `map` list
+
+foo = -3
+
+foo = (+ arg)
+
+foo = (`op` arg)
+
+foo = (arg +)
+
+foo = (arg `op`)
+```
+
+### EnumFrom, EnumFromTo, EnumFromThen, EnumFromThenTo, ParArrayFromTo, ParArrayFromThenTo
+
+``` haskell
+foo = [1 ..]
+
+foo = [1 .. 10]
+
+foo = [1, 2 ..]
+
+foo = [1, 2 .. 10]
+
+foo = [:1 .. 10:]
+
+foo = [:1, 2 .. 10:]
+```
+
+### ListComp, ParComp, and ParArrayComp
+
+``` haskell
+{-# LANGUAGE TransformListComp #-}
+
+foo = [(x, y) | x <- xs, y <- ys]
+
+foo =
+    [(x, y) -- cartesian product
+    | x <- xs -- first list
+    , y <- ys -- second list
+    ]
+
+foo = [(x, y) | x <- xs | y <- ys]
+
+foo =
+    [(x, y) -- zip
+    | x <- xs -- first list
+    | y <- ys -- second list
+    ]
+
+foo = [:(x, y) | x <- xs | y <- ys:]
+
+foo =
+    [:(x, y) -- zip
+    | x <- xs -- first list
+    | y <- ys -- second list
+    :]
+
+foo =
+    [(x, y) | x <- xs
+            , y <- ys
+            , then reverse
+            , then sortWith by (x + y)
+            , then group using permutations
+            , then group by (x + y) using groupWith]
+```
+
+### RecConstr and RecUpdate
+
+``` haskell
+{-# LANGUAGE RecordWildCards #-}
+
+foo =
+    Point
+    { x = 1
+    , y = 2
+    }
+
+foo =
+    Point
+    { x = 1 -- the one
+    , y
+    , ..
+    }
+
+foo =
+    bar
+    { x = 1
+    }
+
+foo =
+    bar
+    { x = 1 -- the one
+    , y
+    , ..
+    }
+```
+
+### Let, If, MultiIf, and Case
+
+``` haskell
+{-# LANGUAGE MultiWayIf #-}
+
+foo =
+    let x = x
+    in x
+
+foo =
+    let x = x -- bottom
+    in
+       -- bottom
+       x
+
+foo =
+    if null xs
+        then None
+        else Some $ head xs
+
+foo =
+    if null xs -- condition
+        then None -- it's empty
+        else Some $ head xs -- it's not
+
+foo =
+    if
+      | null xs -> None
+      | otherwise -> Some $ head xs
+
+foo =
+    if
+      | null xs ->
+          -- it's empty
+          None
+      | otherwise ->
+          -- it's not
+          Some $ head x
+
+foo = case x of
+    True -> False
+    False -> True
+
+foo = case xs of
+    [] ->
+        -- it's empty
+        None
+    x:_ ->
+        -- it's not
+        Some x
+
+foo = case xs of
+    _
+      | null xs -> None
+    _ -> Some $ head x
+```
+
+### Do and MDo
+
+``` haskell
+{-# LANGUAGE RecursiveDo #-}
+
+foo = do
+    return ()
+
+foo = do
+    return ()
+
+foo = do
+    this <- that
+    let this' = tail this
+    if this -- condition
+        then that
+        else those
+
+foo = mdo
+    return ()
+```
+
+### Lambda, LCase
+
+``` haskell
+{-# LANGUAGE LambdaCase #-}
+
+foo = \x -> x
+
+foo = \ ~x -> x
+
+foo = \ !x -> x
+
+foo d = \case
+    Nothing -> d
+    Some x -> x
+```
+
+### BracketExp, SpliceExp, QuasiQuote, VarQuote, and TypQuote
+
+``` haskell
+{-# LANGUAGE TemplateHaskell #-}
+
+mkDecl :: Q Decl
+mkDecl = [d|id x = x|]
+
+mkType :: Q Type
+mkType = [t|(a, b) -> a|]
+
+mkPat :: Q Pat
+mkPat = [p|(a,b)|]
+
+mkExp :: Q Exp
+mkExp = [|a|]
+
+fst :: $(mkType)
+fst $(mkPat) = $(mkExp)
+
+html = [html|<p>Lorem Ipsum Dolor Amet Sit</p>|]
+
+foo = mkSomething 'id 'Nothing ''Maybe
+```
+
+# Regression Tests
+
+## Do
+
+Before comments and onside indent do not mix well.
+
+``` haskell
+foo = do
+    -- comment
+    some expression
+```
+
+## Types
+
+Long types allow linebreaks.
+
+``` haskell
+newtype MyMonadT a b m =
+    MyMonad
+    { runMyMonad
+          :: StateT
+              ([(a, a -> b)])
+              (ReaderT a (ExceptT [IM.IntMap b]) (WriterT [IS.IntSet x] m))
+    }
+```
+
+Promoted types.
+
+``` haskell
+type Foo = Bar 1 "foo" '() '(A, B) '[X, Y]
+```
+
+## Patterns
+
+Long function pattern matches allow linebreaks.
+
+``` haskell
+doThing
+    (Constructor field1 field2 field3)
+    (Constructor field1 field2 field3)
+    (Constructor field1 field2 field3) = undefined
+```
+
+## Onside
+
+Indent within onside started on non-empty line should still not stack.
+
+``` haskell
+foo =
+    if cond
+        then do
+            this
+        else do
+            that
+```
+
+Before comments at the start of onside do not trigger onside.
+
+``` haskell
+foo = do
+    -- comment
+    some expression
+```
+
+Matche arms have individual onside.
+
+``` haskell
+foo True =
+    some -- comment
+        expression
+foo False =
+    some -- comment
+        other
+        expression
+```
+
+Where binds are considered outside of onside.
+
+``` haskell
+foo =
+    some -- comment
+        expression
+  where
+    expression = other
+```
+
+Align overrides onside.
+
+``` haskell
+foo =
+    some
+        expr
+        [ 1 -- comment
+        , 2]
+```
+
+If-then-else must always indent in do blocks.
+
+``` haskell
+foo = do
+    if condition -- comment
+        then this
+        else that
+```
+
+Lists must not suppress onside.
+
+``` haskell
+foo = case x of
+    [y -- comment
+        ,z] -> bar
+
+foo = do
+    [ x -- comment
+        , y]
+```
+
+## Comments
+
+Don't be too eager in assigning comments to the following AST node.
+
+``` haskell
+data Foo =
+    Foo
+    { fooBar :: Text
+      -- ^A comment, long enough to end up on its own line, or at least I hope so.
+    }
+    deriving (Eq)
+```
+
+Keep comments together and aligned.
+
+``` haskell
+-- block
+-- one
+data Foo
+    = Foo  -- some
+           -- comments
+    | Quux -- more
+           -- comments
+-- block
+-- two
+```
+
+... even when haskell-src-exts has weird column span info.
+
+``` haskell
+module Main where
+
+-- comment
+instance Foo Bar where
+    foo = undefined
+
+bar = undefined
+```
+
+Only comments.
+
+``` haskell
+-- some comment
+```
+
+Make sure no comments are dropped from operators or argument.
+
+``` haskell
+foo =
+    some -- comment 1
+    -- comment 2
+    %~ -- comment 3
+    argument -- comment 4
+```
+
+Comments after `where` stay there.
+
+``` haskell
+consM :: Monad m => m a -> Stream m a -> Stream m a
+consM m (Stream step state) = Stream step1 Nothing
+  where
+    {-# INLINE_LATE step1 #-}
+    step1 _ _ = undefined
+```
+
+Comments between declarations do not cause empty lines.
+
+``` haskell
+f :: ()
+--
+f = ()
+```
+
+## Indentation and Line Prefixes
+
+Preserving indentation and line prefixes so that Floskell can be run
+on individual declarations and quoted haskell code.
+
+``` haskell
+    data Enum
+        = One   -- Foo
+        | Two   -- Bar
+        | Three -- Baz
+```
+
+``` haskell
+>
+>    data Enum
+>        = One   -- Foo
+>        | Two   -- Bar
+>        | Three -- Baz
+>
+```
+
+## Module Exports
+
+Long module exports don't force overlong line.
+
+``` haskell
+module SimpleFunctions (identity,compose,append,firstElement,secondElem) where
+```
