packages feed

hindent-6.2.0: TESTS.md

# HIndent test codes

This file is a test suite. Each section maps to an HSpec test, and
each line that is followed by a Haskell code fence is tested to make
sure re-formatting that code snippet produces the same result.

You can browse through this document to see what HIndent's style is
like, or contribute additional sections to it, or regression tests.

## Shebangs

No newlines after a shebang

```haskell given
#!/usr/bin/env stack

-- stack runghc
main =
 pure ()
-- https://github.com/mihaimaruseac/hindent/issues/208
```

```haskell expect
#!/usr/bin/env stack
-- stack runghc
main = pure ()
-- https://github.com/mihaimaruseac/hindent/issues/208
```

Double shebangs

```haskell
#!/usr/bin/env stack
#!/usr/bin/env stack
main = pure ()
```

## Modules

Empty module

```haskell
```

### Module headers

Without an export list

```haskell
module X where

x = 1
```

With an export list

```haskell
module X
  ( x
  , y
  , Z
  , P(x, z)
  , Q(..)
  , module Foo
  ) where
```

With an export list; indentation 4

```haskell 4
module X
    ( x
    , y
    , Z
    , P(x, z)
    ) where
```

### Module-level pragmas

A pragma's name is converted to the SHOUT_CASE.

```haskell given
{-# lAnGuAgE CPP #-}
```

```haskell expect
{-# LANGUAGE CPP #-}
```

Pragmas, GHC options, and haddock options.

```haskell
{-# LANGUAGE CPP #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
{-# OPTIONS_GHC -w #-}
{-# OPTIONS_HADDOCK show-extensions #-}

module Foo where
```

Accept pragmas via `OPTIONS -XFOO`

```haskell
{-# OPTIONS -XPatternSynonyms #-}

import Foo (pattern Bar)
```

Accept pragmas via `OPTIONS_GHC -XFOO`

```haskell
{-# OPTIONS_GHC -XPatternSynonyms #-}

import Foo (pattern Bar)
```

A pragma's length is adjusted automatically

```haskell given
{-#         LANGUAGE OverloadedStrings          #-}
```

```haskell expect
{-# LANGUAGE OverloadedStrings #-}
```

Collect multiple extensions correctly

```haskell
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE PatternSynonyms #-}

import Language.C.Types (pattern TypeName)
```

Collect multiple extensions separated by commas correctly

```haskell given
{-# LANGUAGE TypeApplications,
    PatternSynonyms #-}

import Foo (pattern Bar)

foo = bar @Int 3
```

```haskell expect
{-# LANGUAGE TypeApplications, PatternSynonyms #-}

import Foo (pattern Bar)

foo = bar @Int 3
```

Do not collect pragma-like comments

```haskell
-- {-# LANGUAGE StaticPointers #-}
{-

{-# LANGUAGE StaticPointers #-}

-}
-- @static@ is no longer a valid identifier
-- once `StaticPointers` is enabled.
static = 3
```

#### `WARNING`

Without messages and an export list.

```haskell
module Foo {-# WARNING [] #-} where
```

With a string without an export list.

```haskell
module Foo {-# WARNING "Debug purpose only." #-} where
```

With a list of reasons without an export list.

```haskell
module Foo {-# WARNING ["Debug purpose only.", "Okay?"] #-} where
```

#### `DEPRECATED`

Without messages and an export list.

```haskell
module Foo {-# DEPRECATED [] #-} where
```

With a string without an export list.

```haskell
module Foo {-# DEPRECATED "Use Bar." #-} where
```

With a list of reasons and an export list.

```haskell
module Foo {-# DEPRECATED ["Use Bar.", "Or use Baz."] #-}
  ( x
  , y
  , z
  ) where
```

## Imports, foreign imports, and foreign exports

Import lists

```haskell
import Control.Lens (_2, _Just)
import Data.Text
import Data.Text
import qualified Data.Text as T
import qualified Data.Text (a, b, c)
import Data.Text (a, b, c)
import Data.Text hiding (a, b, c)
```

Shorter identifiers come first

```haskell
import Foo ((!), (!!))
```

Import with `ExplicitNamespaces`.

```haskell
{-# LANGUAGE ExplicitNamespaces #-}

import Prlude (type FilePath)
```

Import a pattern

```haskell
{-# LANGUAGE PatternSynonyms #-}

import Foo (pattern Bar)
```

Sorted

```haskell given
import B
import A
```

```haskell expect
import A
import B
```

Explicit imports - capitals first (typeclasses/types), then operators, then identifiers

```haskell given
import qualified MegaModule as M ((>>>), MonadBaseControl, void, MaybeT(..), join, Maybe(Nothing, Just), liftIO, Either, (<<<), Monad(return, (>>=), (>>)))
```

```haskell expect
import qualified MegaModule as M
  ( Either
  , Maybe(Just, Nothing)
  , MaybeT(..)
  , Monad((>>), (>>=), return)
  , MonadBaseControl
  , (<<<)
  , (>>>)
  , join
  , liftIO
  , void
  )
```

Pretty import specification

```haskell
{-# LANGUAGE ForeignFunctionInterface #-}

import A hiding
  ( foobarbazqux
  , foobarbazqux
  , foobarbazqux
  , foobarbazqux
  , foobarbazqux
  , foobarbazqux
  , foobarbazqux
  )

import Name hiding ()

import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
```

An import declaration importing lots of data constructors

```haskell
import Language
  ( Language(Ada, Ada, Assembly, C, CPlusPlus, CSharp, Clojure, Cobol, Dart, Elixir,
             Elm, Erlang, Fortran, Go, Groovy, Haskell, Java, JavaScript, Julia,
             Kotlin, Lisp, Lua, ObjectiveC, PHP, Pascal, Perl, Prolog, Python, Ruby,
             Rust, Scala)
  , allLanguages
  )
```

Preserve newlines between import groups

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/200
import GHC.Monad

import CommentAfter -- Comment here shouldn't affect newlines
import HelloWorld

import CommentAfter -- Comment here shouldn't affect newlines

-- Comment here shouldn't affect newlines
import CommentAfter
```

`PackageImports`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/480
{-# LANGUAGE PackageImports #-}

import qualified "base" Prelude as P
```

`ImportQualifiedPost`

```haskell
{-# LANGUAGE ImportQualifiedPost #-}

import Data.Text qualified as T
```

Importing a `#`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/547
import Diagrams.Prelude ((#))
```

### Foreign imports and exports

A `ccall` foreign export

```haskell
{-# LANGUAGE ForeignFunctionInterface #-}

foreign export ccall "test" test :: IO ()
```

A `ccall` unsafe foreign import

```haskell
{-# LANGUAGE ForeignFunctionInterface #-}

foreign import ccall unsafe "test" test :: IO ()
```

A `capi` foreign import

```haskell
{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE ForeignFunctionInterface #-}

foreign import capi safe "foo" test :: IO Int
```

A `stdcall` foreign import

```haskell
{-# LANGUAGE ForeignFunctionInterface #-}

foreign import stdcall safe "test" bar :: IO ()
```

A `prim` foreign import

```haskell
{-# LANGUAGE ForeignFunctionInterface #-}

foreign import prim safe "test" test :: IO ()
```

A `javascript` foreign import

```haskell
{-# LANGUAGE ForeignFunctionInterface #-}

foreign import javascript safe "test" test :: IO ()
```

## Declarations

Data family

```haskell
data family Foo a
```

`StandaloneKindSignatures`

```haskell
{-# LANGUAGE StandaloneKindSignatures #-}

type Foo :: Type -> Type -> Type
data Foo a b =
  Foo a b
```

Default declaration

```haskell
default (Integer, Double)
```

### `ANN` pragmas

Value annotation.

```haskell
{-# ANN foo "annotation" #-}
```

Type annotation.

```haskell
{-# ANN type Foo "annotation" #-}
```

Module annotation.

```haskell
{-# ANN module "annotation" #-}
```

### Class declarations

Default signatures

```haskell
-- https://github.com/chrisdone/hindent/issues/283
class Foo a where
  bar :: a -> a -> a
  default bar :: Monoid a => a -> a -> a
  bar = mappend
```

`TypeOperators` and `MultiParamTypeClasses`

```haskell
-- https://github.com/chrisdone/hindent/issues/277
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}

class (a :< b) c
```

#### Class constraints

Empty

```haskell
class () =>
      Foo a
```

Long

```haskell
class ( Foo a
      , Bar a
      , Baz a
      , Hoge a
      , Fuga a
      , Piyo a
      , Hogera a
      , Hogehoge a
      , Spam a
      , Ham a
      ) =>
      Quux a
```

#### Class methods

With class constraints

```haskell
class Foo f where
  myEq :: (Eq a) => f a -> f a -> Bool
```

Long signatures

```haskell
class Foo a where
  fooBarBazQuuxHogeFuga ::
       a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a
```

#### Associated type synonyms

Associated type synonyms

```haskell
class Foo a where
  type Bar b
```

Associated type synonyms annotated with injectivity information

```haskell
-- https://github.com/commercialhaskell/hindent/issues/528
class C a where
  type F a = b | b -> a
```

### Class instance declarations

Without methods

```haskell
instance C a
```

With methods

```haskell
instance C a where
  foobar = do
    x y
    k p
```

With type operators

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/342
instance Foo (->)

instance Foo (^>)

instance Foo (T.<^)
```

With a type alias

```haskell
instance Foo a where
  type Bar a = Int
```

A `where` clause between instance functions

```haskell
instance Pretty HsModule where
  pretty' = undefined
    where
      a = b
  commentsBefore = Nothing
```

With a `SPECIALISE` pragma

```haskell
instance (Show a) => Show (Foo a) where
  {-# SPECIALISE instance Show (Foo String) #-}
  show = undefined
```

With associated data types

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/493
instance GM 'Practice where
  data MatchConfig 'Practice = MatchConfig'Practice
    { teamSize :: Int
    , ladder :: Ladder
    }
```

With associated newtypes

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/837
instance Foo a where
  newtype Bar a =
    FooBar a
```

#### With overlapping pragmas

`OVERLAPPING`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/386
instance {-# OVERLAPPING #-} Arbitrary (Set Int) where
  arbitrary = undefined
```

`OVERLAPPABLE`

```haskell
instance {-# OVERLAPPABLE #-} Arbitrary Int where
  arbitrary = undefined
```

`OVERLAPS`

```haskell
instance {-# OVERLAPS #-} Arbitrary String where
  arbitrary = undefined
```

`INCOHERENT`

```haskell
instance {-# INCOHERENT #-} Arbitrary String where
  arbitrary = undefined
```

#### With class constraints

Short name

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/244
instance Num a => C a
```

Long name

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/244
instance Nuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum a =>
         C a where
  f = undefined
```

#### Explicit foralls

Without class constraints

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/218
instance forall x. C
```

With class constraints

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/218
instance forall x. Show x => C x
```

#### Symbol class constructor

Infix

```haskell
instance Bool :?: Bool
```

Prefix

```haskell
instance (:?:) Int Bool
```

### Data declarations

Data declaration with underscore

```haskell
data Stanza = MkStanza
  { _stanzaBuildInfo :: BuildInfo
  , stanzaIsSourceFilePath :: FilePath -> Bool
  }
```

A data declaration with typeclass constraints

```haskell
data Ord a =>
     Foo =
  Foo a
```

Multiple constructors at once

```haskell
data Foo = Foo
  { foo, bar, baz, qux, quux :: Int
  }
```

No fields

```haskell
data Foo
```

Single field

```haskell
data Foo =
  Foo
```

Multiple unnamed fields

```haskell
data HttpException
  = InvalidStatusCode Int
  | MissingContentHeader
```

A lot of unnamed fields in a constructor

```haskell
data Foo =
  Foo
    String
    String
    String
    String
    String
    String
    String
    String
    String
    String
    String
```

A banged field

```haskell
data Foo =
  Foo !Int
```

A record constructor with a field

```haskell
data Foo = Foo
  { foo :: Int
  }
```

Multiple constructors with fields

```haskell
data Expression a
  = VariableExpression
      { id :: Id Expression
      , label :: a
      }
  | FunctionExpression
      { var :: Id Expression
      , body :: Expression a
      , label :: a
      }
  | ApplyExpression
      { func :: Expression a
      , arg :: Expression a
      , label :: a
      }
  | ConstructorExpression
      { id :: Id Constructor
      , label :: a
      }
```

A mixture of constructors with unnamed fields and record constructors

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/393
data X
  = X
      { x :: Int
      , x' :: Int
      }
  | X'
```

An infix data constructor

```haskell
data Foo =
  Int :--> Int
```

An `UNPACK`ed field.

```haskell
data Foo = Foo
  { x :: {-# UNPACK #-} Int
  }
```

An `NOUNPACK`ed field.

```haskell
data Foo = Foo
  { x :: {-# NOUNPACK #-} !Int
  }
```

A lazy field.

```haskell
data Foo = Foo
  { x :: ~Int
  }
```

#### Fields with `forall` constraints

Single

```haskell
data D =
  forall a. D a
```

Multiple

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/443
{-# LANGUAGE ExistentialQuantification #-}

data D =
  forall a b c. D a b c
```

With an infix constructor

```haskell
data D =
  forall a. a :== a
```

#### Fields with contexts

Without a `forall`

```haskell
data Foo =
  Eq a => Foo a
```

With a `forall`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/278
data Link c1 c2 a c =
  forall b. (c1 a b, c2 b c) =>
            Link (Proxy b)
```

With an infix constructor without a `forall`

```haskell
data Foo =
  Eq a => a :== a
```

With an infix constructor with a `forall`

```haskell
data Foo =
  forall a. Eq a =>
            a :== a
```

#### Derivings

With a single constructor

```haskell
data Simple =
  Simple
  deriving (Show)
```

With multiple constructors

```haskell
data Stuffs
  = Things
  | This
  | That
  deriving (Show)
```

With a record constructor

```haskell
-- From https://github.com/mihaimaruseac/hindent/issues/167
data Person = Person
  { firstName :: !String -- ^ First name
  , lastName :: !String -- ^ Last name
  , age :: !Int -- ^ Age
  } deriving (Eq, Show)
```

Multiple derivings

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/289
newtype Foo =
  Foo Proxy
  deriving ( Functor
           , Applicative
           , Monad
           , Semigroup
           , Monoid
           , Alternative
           , MonadPlus
           , Foldable
           , Traversable
           )
```

Various deriving strategies

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/503
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Foo where

import Data.Typeable
import GHC.Generics

newtype Number a =
  Number a
  deriving (Generic)
  deriving stock (Ord)
  deriving newtype (Eq)
  deriving anyclass (Typeable)
  deriving (Show) via a
```

`StandaloneDeriving`

```haskell
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE StandaloneDeriving #-}

data Foo =
  Foo

deriving instance Eq Foo

deriving stock instance Ord Foo

deriving via (Foo a) instance Show (Bar a)
```

#### GADT declarations

With a kind signature

```haskell
data Ty :: (* -> *) where
  TCon
    :: { field1 :: Int
       , field2 :: Bool}
    -> Ty Bool
  TCon' :: (a :: *) -> a -> Ty a
```

Without a kind signature

```haskell
data Foo where
  Foo
    :: forall v. Ord v
    => v
    -> v
    -> Foo
```

With a `forall` but no contexts

```haskell
data Foo where
  Foo :: forall v. v -> v -> Foo
```

With a context but no `forall`s

```haskell
data Foo where
  Foo :: (Ord v) => v -> v -> Foo
```

With methods with record signatures

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/581
data Test where
  Test :: Eq a => { test :: a } -> Test
```

### Data instance declarations

Without type applications

```haskell
data instance Foo Int =
  FInt
```

With type applications

```haskell
data instance Foo @k a =
  FString
```

### Function declarations

Case inside `do` and lambda

```haskell
foo =
  \x -> do
    case x of
      Just _ -> 1
      Nothing -> 2
```

A `case` inside a `let`.

```haskell
f = do
  let (x, xs) =
        case gs of
          [] -> undefined
          (x':xs') -> (x', xs')
  undefined
```

A `do` inside a lambda.

```haskell
printCommentsAfter =
  case commentsAfter p of
    xs -> do
      forM_ xs $ \(L loc c) -> do
        eolCommentsArePrinted
```

Case with natural pattern (See NPat of https://hackage.haskell.org/package/ghc-lib-parser-9.2.3.20220527/docs/Language-Haskell-Syntax-Pat.html#t:Pat)

```haskell
foo =
  case x of
    0 -> pure ()
    _ -> undefined
```

```haskell
s8_stripPrefix bs1@(S.PS _ _ l1) bs2
  | bs1 `S.isPrefixOf` bs2 = Just (S.unsafeDrop l1 bs2)
  | otherwise = Nothing
```

A `do` inside a guard arm

```haskell
f
  | x == 1 = do
    a
    b
```

`if` having a long condition

```haskell
foo =
  if fooooooo
       || baaaaaaaaaaaaaaaaaaaaa
       || apsdgiuhasdpfgiuahdfpgiuah
       || bazzzzzzzzzzzzz
    then a
    else b
```

A long signature inside a where clause

```haskell
cppSplitBlocks :: ByteString -> [CodeBlock]
cppSplitBlocks inp = undefined
  where
    spanCPPLines ::
         [(Int, ByteString)] -> ([(Int, ByteString)], [(Int, ByteString)])
    spanCPPLines = undefined
```

A `forall` type inside a where clause

```haskell
replaceAllNotUsedAnns :: HsModule -> HsModule
replaceAllNotUsedAnns = everywhere app
  where
    app ::
         forall a. Data a
      => (a -> a)
    app = undefined

f :: a
f = undefined
  where
    ggg ::
         forall a. Typeable a
      => a
      -> a
    ggg = undefined
```

Prefix notation for operators

```haskell
(+) a b = a
```

Guards and pattern guards

```haskell
f x
  | x <- Just x
  , x <- Just x =
    case x of
      Just x -> e
  | otherwise = do
    e
  where
    x = y
```

Where clause

```haskell
sayHello = do
  name <- getLine
  putStrLn $ greeting name
  where
    greeting name = "Hello, " ++ name ++ "!"
```

An empty line is inserted after an empty `where`

```haskell given
f = evalState
    -- A comment
  where
```

```haskell expect
f = evalState
    -- A comment
  where

```

Multiple function declarations with an empty `where`

```haskell
f = undefined
  where


g = undefined
```

Let inside a `where`

```haskell
g x =
  let x = 1
   in x
  where
    foo =
      let y = 2
          z = 3
       in y
```

The indent after a top-level `where` has always 2 spaces.

```haskell 4
f = undefined
  where
    g = undefined
```

The indent after a `where` inside a `case` depends on the indent space setting

```haskell 4
f =
    case x of
        x -> undefined
            where y = undefined
```

#### Pattern matchings

View pattern

```haskell
foo (f -> Just x) = print x
foo _ = Nothing
```

Match against a list

```haskell
head [] = undefined
head [x] = x
head xs = head $ init xs

foo [Coord _ _, Coord _ _] = undefined
```

Multiple matchings

```haskell
head' [] = Nothing
head' (x:_) = Just x
```

n+k patterns

```haskell
{-# LANGUAGE NPlusKPatterns #-}

f (n+5) = 0
```

Binary symbol data constructor in pattern

```haskell
f (x :| _) = x

f' ((:|) x _) = x

f'' ((Data.List.NonEmpty.:|) x _) = x

g (x:xs) = x

g' ((:) x _) = x
```

Infix constructor pattern

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/424
a = from $ \(author `InnerJoin` post) -> pure ()
```

Unboxed sum pattern matching.

```haskell
{-# LANGUAGE UnboxedSums #-}

f (# (# n, _ #) | #) = (# n | #)
f (# | b #) = (# | b #)
```

Pattern matching against a infix constructor with a module name prefix

```haskell
foo (a FOO.:@: b) = undefined
```

##### Pattern matchings against record

Short

```haskell
fun Rec {alpha = beta, gamma = delta, epsilon = zeta, eta = theta, iota = kappa} = do
  beta + delta + zeta + theta + kappa
```

Long

```haskell
fun Rec { alpha = beta
        , gamma = delta
        , epsilon = zeta
        , eta = theta
        , iota = kappa
        , lambda = mu
        } =
  beta + delta + zeta + theta + kappa + mu + beta + delta + zeta + theta + kappa
```

Another long one

```haskell
resetModuleStartLine m@HsModule { hsmodAnn = epa@EpAnn {..}
                                , hsmodName = Just (L (SrcSpanAnn _ (RealSrcSpan sp _)) _)
                                } = undefined
```

Symbol constructor, short

```haskell
fun ((:..?) {}) = undefined
```

Symbol constructor, long

```haskell
fun (:..?) { alpha = beta
           , gamma = delta
           , epsilon = zeta
           , eta = theta
           , iota = kappa
           , lambda = mu
           } =
  beta + delta + zeta + theta + kappa + mu + beta + delta + zeta + theta + kappa
```

Symbol field

```haskell
f (X {(..?) = x}) = x
```

Punned symbol field

```haskell
f' (X {(..?)}) = (..?)
```

`RecordWileCards`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/274
foo (bar@Bar {..}) = Bar {..}

resetModuleNameColumn m@HsModule {hsmodName = Just (L (SrcSpanAnn epa@EpAnn {..} sp) name)} =
  m

bar Bar {baz = before, ..} = Bar {baz = after, ..}
```

As pattern

```haskell
f all@(x:xs) = all
```

### Infix declarations

infixl

```haskell
infixl 1 ^-^
```

infixr

```haskell
infixr 1 ^-^
```

infix

```haskell
infix 1 ^-^
```

### Pattern synonym declarations

Unidirectional with a pattern type signature

```haskell
{-# LANGUAGE PatternSynonyms #-}

pattern Foo :: Int -> Int -> [Int]
pattern Foo x y <- [x, y]
```

Bidirectional record pattern

```haskell
{-# LANGUAGE PatternSynonyms #-}

pattern Pair {x, y} = (x, y)
```

#### Explicit bidirectional

With a prefix constructor

```haskell
{-# LANGUAGE PatternSynonyms #-}

pattern Fst x <- (x, x)
  where Fst x = (x, 0)
```

With an infix constructor

```haskell
{-# LANGUAGE PatternSynonyms #-}

pattern x :| xs <- x : xs
  where a :| b = a : b
```

### Pragma declarations

`INLINE`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/255
{-# INLINE f #-}
f :: Int -> Int
f n = n
```

`NOINLINE` with an operator enclosed by parentheses

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/415
{-# NOINLINE (<>) #-}
```

`INLINABLE`

```haskell
{-# INLINABLE f #-}
f :: a
f = undefined
```

`OPAQUE`

```haskell since 9.4.0
{-# OPAQUE f #-}
f :: a
f = undefined
```

`INLINE` with levels

```haskell
{-# INLINE [0] f #-}
{-# INLINE [~1] g #-}
```

A `DEPRECATED`.

```haskell
{-# DEPRECATED
giveUp "Never give up."
 #-}

giveUp = undefined
```

A `WARNING`.

```haskell
{-# WARNING
debugCode "The use of 'debugCode'"
 #-}
```

A `COMPLETE`

```haskell
{-# COMPLETE Single, Anylist #-}
```

Top-level `SPECIALISE`

```haskell
{-# SPECIALISE lookup :: [(Int, Int)] -> Int -> Maybe Int #-}
```

Multiple signatures in a `SPECIALISE`

```haskell
-- https://github.com/mihaimaruseac/hindent/pull/784
{-# SPECIALISE foo :: Int -> Int, Double -> Double #-}
```

A `SCC`

```haskell
{-# SCC bar #-}
```

#### Rule declarations

Without `forall`s

```haskell
{-# RULES
"foo/bar" foo = bar
 #-}
```

With `forall` but no type signatures

```haskell
{-# RULES
"piyo/pochi" forall a. piyo a = pochi a a
 #-}
```

With `forall` and type signatures

```haskell
{-# RULES
"hoge/fuga" forall (a :: Int). hoge a = fuga a a
 #-}
```

### Role annotation declarations

`normal`

```haskell
{-# LANGUAGE RoleAnnotations #-}

type role Foo nominal
```

`representational`

```haskell
{-# LANGUAGE RoleAnnotations #-}

type role Bar representational
```

`phantom`

```haskell
{-# LANGUAGE RoleAnnotations #-}

type role Baz phantom
```

### Type family declarations

Without annotations

```haskell
type family Id a
```

With annotations

```haskell
type family Id a :: *
```

With injectivity annotations

```haskell
type family Id a = r | r -> a
```

Closed type families

```haskell
type family Closed (a :: k) :: Bool where
  Closed (x @Int) = 'Int
  Closed x = 'True
```

### Type family instance declarations

Without holes

```haskell
type instance Id Int = Int
```

With a hole

```haskell
type instance Id _ = String
```

### Type signature declarations

Multiple function signatures at once

```haskell
a, b, c :: Int
```

Type using a numeric value

```haskell
f :: Foo 0
```

Type using a character value

```haskell
f :: Foo 'a'
```

Type using a unicode string value

```haskell
f :: Foo "あ"
```

A dot not enclosed by spaces is printed correctly if `OverloadedRecordDot` is not enabled.

```haskell given
f :: forall a.(Data a, Typeable a) => a
```

```haskell expect
f :: forall a. (Data a, Typeable a)
  => a
```

Short

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/390
fun :: Short
fun = undefined
```

Always break after `::` on overlong signatures

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/390
someFunctionSignature ::
     Wiiiiiiiiiiiiiiiiith
  -> Enough
  -> (Arguments -> To ())
  -> Overflow (The Line Limit)
```

A long type is broken into lines

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/359
thing ::
     ( ResB.BomEx
     , Maybe
         [( Entity BomSnapshot
          , ( [ResBS.OrderSubstituteAggr]
            , ( Maybe (Entity BomSnapshotHistory)
              , Maybe (Entity BomSnapshotHistory))))])
  -> [(ResB.BomEx, Maybe ResBS.BomSnapshotAggr)]
```

Long parameter list with a `forall`

```haskell
fooooooooo ::
     forall a.
     Fooooooooooooooo a
  -> Fooooooooooooooo a
  -> Fooooooooooooooo a
  -> Fooooooooooooooo a
```

Implicit parameters

```haskell
{-# LANGUAGE ImplicitParams #-}

f :: (?x :: Int) => Int
```

Quasiquotes in types

```haskell
{-# LANGUAGE QuasiQuotes #-}

fun :: [a|bc|]
```

Tuples

```haskell
fun :: (a, b, c) -> (a, b)
```

Infix operator

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/301
(+) :: ()
```

With a record

```haskell
url :: r {url :: String} => r -> Integer
```

`forall` type

```haskell
f :: (forall a. Data a => a -> a) -> (forall a b. Data a => a -> b)
g :: forall a b. a -> b
```

An infix operator containing `#`

```haskell
(#!) :: Int -> Int -> Int
```

Multiple line function signature inside a `where`

```haskell 4
foo = undefined
  where
    go :: Fooooooooooooooooooooooo
       -> Fooooooooooooooooooooooo
       -> Fooooooooooooooooooooooo
       -> Fooooooooooooooooooooooo
    go = undefined
```

Types with many type applications

```haskell
foo ::
     Foo
       LongLongType
       LongLongType
       LongLongType
       LongLongType
       LongLongType
       LongLongType
  -> Int
```

#### Promoted types

Class constraints should leave `::` on same line

```haskell
-- see https://github.com/chrisdone/hindent/pull/266#issuecomment-244182805
fun ::
     (Class a, Class b)
  => fooooooooooo bar mu zot
  -> fooooooooooo bar mu zot
  -> c
```

An infix operator containing `#`

```haskell
(#!) :: Int -> Int -> Int
```

Prefix promoted symbol type constructor

```haskell
a :: '(T.:->) 'True 'False
b :: (T.:->) 'True 'False
c :: '(:->) 'True 'False
d :: (:->) 'True 'False
```

##### Promoted lists

Short

```haskell
fun1 :: Def ('[ Ref s (Stored Uint32), IBool] T.:-> IBool)
fun1 = undefined

fun2 :: Def ('[ Ref s (Stored Uint32), IBool] :-> IBool)
fun2 = undefined
```

Long

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/522
type OurContext
  = '[ AuthHandler W.Request (ExtendedPayloadWrapper UserSession)
     , BasicAuthCheck GameInstanceId
     , BasicAuthCheck (RegionId, RegionName)
     , BasicAuthCheck Alert.SourceId
     , M.MultipartOptions M.Tmp
     ]
```

Nested

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/348
a :: A '[ 'True]
-- nested promoted list with multiple elements.
b :: A '[ '[ 'True, 'False], '[ 'False, 'True]]
```

#### Symbol type constructors

Infix

```haskell
f :: a :?: b
```

Prefix

```haskell
f' :: (:?:) a b
```

#### Type signature with class constraints

Single

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/244
x :: Num a => a
x = undefined
```

Multiple

```haskell
fun :: (Class a, Class b) => a -> b -> c
```

Multiple without parentheses

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/554
g :: Semigroup a => Monoid a => Maybe a -> a
```

Long constraints

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/222
foo ::
     ( Foooooooooooooooooooooooooooooooooooooooooo
     , Foooooooooooooooooooooooooooooooooooooooooo
     )
  => A
```

Class constraints should leave `::` on same line

```haskell
-- see https://github.com/mihaimaruseac/hindent/pull/266#issuecomment-244182805
fun ::
     (Class a, Class b)
  => fooooooooooo bar mu zot
  -> fooooooooooo bar mu zot
  -> c
```

Symbol class constructor in class constraint

```haskell
f :: (a :?: b) => (a, b)
f' :: ((:?:) a b) => (a, b)
```

#### Unboxed types

Short unboxed sums

```haskell
{-# LANGUAGE UnboxedSums #-}

f :: (# (# Int, String #) | String #) -> (# Int | String #)
```

Long unboxed sums

```haskell
{-# LANGUAGE UnboxedSums #-}

f' ::
     (# (# Int, String #)
      | Either Bool Int
      | Either Bool Int
      | Either Bool Int
      | Either Bool Int
      | Either Bool Int
      | String #)
  -> (# Int | String #)
```

Large unboxed tuples

```haskell
{-# LANGUAGE UnboxedTuples #-}

f :: (# Looooooooooooooooooooooooooooooooooooooooooooong
      , Looooooooooooooooooooooooooooooooooooooooooooong
      , Looooooooooooooooooooooooooooooooooooooooooooong #)
```

### Type synonym declarations

Short

```haskell
type EventSource a = (AddHandler a, a -> IO ())
```

Long

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/290
type MyContext m
  = ( MonadState Int m
    , MonadReader Int m
    , MonadError Text m
    , MonadMask m
    , Monoid m
    , Functor m)
```

Very higher-kinded type

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/534
type SomeTypeSynonym
  = RecordWithManyFields
      FieldNumber1
      FieldNumber2
      FieldNumber3
      FieldNumber4
      FieldNumber5
      FieldNumber6
      FieldNumber7
      FieldNumber8
      FieldNumber9
      FieldNumber10
      FieldNumber11
      FieldNumber12
      FieldNumber13
      FieldNumber14
      FieldNumber15
```

Infix type constructor

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/417
type API = api1 :<|> api2
```

Type with a string

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/451
type Y = X "abc\n\n\ndef"
```

`TypeOperators`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/277
{-# LANGUAGE TypeOperators #-}

type m ~> n = ()
```

#### Functional dependencies

Single

```haskell
-- https://github.com/commercialhaskell/hindent/issues/323
class Foo a b | a -> b where
  f :: a -> b
```

Multiple dependencies in a line

```haskell
class Foo a b | a -> b, b -> a
```

Long

```haskell
-- https://github.com/commercialhaskell/hindent/issues/323
class Foo a b c d e f
  | a b c d e -> f
  , a b c d f -> e
  , a b c e f -> d
  , a b d e f -> c
  , a c d e f -> b
  , b c d e f -> a
  where
  foo :: a -> b -> c -> d -> e -> f
```

#### With class constraints

Single

```haskell
-- https://github.com/commercialhaskell/hindent/issues/459
class Class1 a =>
      Class2 a
  where
  f :: a -> Int
```

Multiple

```haskell
-- https://github.com/commercialhaskell/hindent/issues/459
class (Eq a, Show a) =>
      Num a
  where
  (+), (-), (*) :: a -> a -> a
  negate :: a -> a
  abs, signum :: a -> a
  fromInteger :: Integer -> a
```

#### MINIMAL pragmas

Monad example

```haskell
class A where
  {-# MINIMAL return, ((>>=) | (join, fmap)) #-}
```

Very long names #310

```haskell
class A where
  {-# MINIMAL averylongnamewithnoparticularmeaning
            | ananotherverylongnamewithnomoremeaning #-}
```

## Expressions

A minus sign

```haskell
f = -(3 + 5)
```

Lists

```haskell
exceptions = [InvalidStatusCode, MissingContentHeader, InternalServerError]

exceptions =
  [ InvalidStatusCode
  , MissingContentHeader
  , InternalServerError
  , InvalidStatusCode
  , MissingContentHeader
  , InternalServerError
  ]
```

Multi-way if

```haskell
x =
  if | x <- Just x
     , x <- Just x ->
       case x of
         Just x -> e
         Nothing -> p
     | otherwise -> e
```

Type application

```haskell
{-# LANGUAGE TypeApplications #-}

a = fun @Int 12
```

An expression with a SCC pragma

```haskell
foo = {-# SCC foo #-} undefined
```

A hole

```haskell
foo = 3 + _
```

Implicit value

```haskell
{-# LANGUAGE ImplicitParams #-}

foo = ?undefined
```

`UnboxedSums`

```haskell
{-# LANGUAGE UnboxedSums #-}

f = (# | Bool #)
```

`StaticPointers`

```haskell
{-# LANGUAGE StaticPointers #-}

f = static 1
```

`OverloadedLabels`

```haskell
{-# LANGUAGE OverloadedLabels #-}

f = #foo
```

### Arrows

`-<`

```haskell
{-# LANGUAGE Arrows #-}

f =
  proc foo -> do
    bar -< baz
    aaa >- bbb
```

`-<<`

```haskell
{-# LANGUAGE Arrows #-}

f =
  proc foo -> do
    g bar -<< baz
    aaaaa >>- h bbb
```

`(| ... |)`

```haskell
{-# LANGUAGE Arrows #-}

f = proc g -> (|foo (bar -< g) (baz -< g)|) zz
```

Lambda equation.

```haskell
{-# LANGUAGE Arrows #-}

f = proc g -> \x -> x -< g
```

Case expression.

```haskell
{-# LANGUAGE Arrows #-}

f =
  proc g ->
    case h of
      [] -> i -< ()
      (_:_) -> j -< ()
```

Lambda case

```haskell
{-# LANGUAGE Arrows #-}
{-# LANGUAGE LambdaCase #-}

f =
  proc g ->
    \case
      _ -> h -< ()
```

`if ... then ... else`

```haskell
{-# LANGUAGE Arrows #-}

f =
  proc g ->
    if x
      then h -< g
      else t -< g
```

`let ... in`

```haskell
{-# LANGUAGE Arrows #-}

f =
  proc g ->
    let x = undefined
        y = undefined
     in returnA -< g
```

### Case expressions

Normal case

```haskell
strToMonth :: String -> Int
strToMonth month =
  case month of
    "Jan" -> 1
    "Feb" -> 2
    _ -> error $ "Unknown month " ++ month
```

Inside a `where` and `do`

```haskell
g x =
  case x of
    a -> x
  where
    foo =
      case x of
        _ -> do
          launchMissiles
      where
        y = 2
```

Empty case

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/414
{-# LANGUAGE EmptyCase #-}

f1 = case () of {}
```

Empty lambda case

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/414
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE LambdaCase #-}

f2 = \case {}
```

A guard in a case

```haskell
f =
  case g of
    []
      | even h -> Nothing
    _ -> undefined
```

cases

```haskell since 9.4.1
{-# LANGUAGE Arrows #-}
{-# LANGUAGE LambdaCase #-}

foo =
  \cases
    1 1 -> 1
    _ _ -> 2
```

### `do` expressions

Long function applications

```haskell
test = do
  alphaBetaGamma deltaEpsilonZeta etaThetaIota kappaLambdaMu nuXiOmicron piRh79
  alphaBetaGamma deltaEpsilonZeta etaThetaIota kappaLambdaMu nuXiOmicron piRho80
  alphaBetaGamma
    deltaEpsilonZeta
    etaThetaIota
    kappaLambdaMu
    nuXiOmicron
    piRhoS81
```

Do as a left-hand side of an infix operation

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/238
-- https://github.com/mihaimaruseac/hindent/issues/296
block = do
  ds <- inBraces $ inWhiteSpace declarations
  return $ Block ds
  <?> "block"
```

#### Bindings

Short

```haskell
foo = do
  mcp <- findCabalFiles (takeDirectory abssrcpath) (takeFileName abssrcpath)
  print mcp
```

Large

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/221
x = do
  config <- execParser options
  comments <-
    case config of
      Diff False args -> commentsFromDiff args
      Diff True args -> commentsFromDiff ("--cached" : args)
      Files args -> commentsFromFiles args
  mapM_ (putStrLn . Fixme.formatTodo) (concatMap Fixme.getTodos comments)
```

#### `let` bindings

With type signatures but no class constraints

```haskell
f = do
  let g :: Int
      g = 3
  print g
```

With both type signatures and class constraints

```haskell
f = do
  let try :: Typeable b => b
      try = undefined
  undefined
```

#### `RecursiveDo`

`rec`

```haskell
{-# LANGUAGE RecursiveDo #-}

f = do
  a <- foo
  rec b <- a c
      c <- a b
  return $ b + c
```

`mdo`

```haskell
{-# LANGUAGE RecursiveDo #-}

g = mdo
  foo
  bar
```

#### `QualifiedDo`

Qualified do

```haskell
{-# LANGUAGE QualifiedDo #-}

f = Module.Path.do
  a <- foo
  return a
```

Qualified do with `mdo`

```haskell
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE QualifiedDo #-}

f = Module.Path.mdo
  a <- foo
  return a
```

### Function applications

Long line, tuple

```haskell
a =
  test
    (alphaBetaGamma, deltaEpsilonZeta, etaThetaIota, kappaLambdaMu, nuXiOmic79)
    (alphaBetaGamma, deltaEpsilonZeta, etaThetaIota, kappaLambdaMu, nuXiOmicr80)
    ( alphaBetaGamma
    , deltaEpsilonZeta
    , etaThetaIota
    , kappaLambdaMu
    , nuXiOmicro81)
```

Long line, tuple section

```haskell
a =
  test
    (, alphaBetaGamma, , deltaEpsilonZeta, , etaThetaIota, kappaLambdaMu, nu79)
    (, alphaBetaGamma, , deltaEpsilonZeta, , etaThetaIota, kappaLambdaMu, nuX80)
    (
    , alphaBetaGamma
    ,
    , deltaEpsilonZeta
    ,
    , etaThetaIota
    , kappaLambdaMu
    , nuXi81
    ,)
```

Linebreaks after very short names if the total line length goes over the limit

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/405
t =
  f "this is a very loooooooooooooooooooooooooooong string that goes over the line length"
    argx
    argy
    argz

t =
  function
    "this is a very loooooooooooooooooooooooooooong string that goes over the line length"
    argx
    argy
    argz
```

### Lambda expressions

Lazy patterns

```haskell
f = \ ~a -> undefined
-- \~a yields parse error on input ‘\~’
```

Bang patterns

```haskell
f = \ !a -> undefined
-- \!a yields parse error on input ‘\!’
```

An infix operator with a lambda expression

```haskell
a =
  for xs $ \x -> do
    left x
    right x
```

Nested lambdas

```haskell
foo :: IO ()
foo =
  alloca 10 $ \a ->
    alloca 20 $ \b ->
      cFunction fooo barrr muuu (fooo barrr muuu) (fooo barrr muuu)
```

In a `case`

```haskell
f x =
  case filter (\y -> isHappy y x) of
    [] -> Nothing
    (z:_) -> Just (\a b -> makeSmile z a b)
```

### Let ... in expressions

With bang parameters

```haskell
f =
  let !x = 3
   in x
```

With implicit parameters

```haskell
{-# LANGUAGE ImplicitParams #-}

f =
  let ?x = 42
   in f
```

inside a `do`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/467
main :: IO ()
main = do
  let x = 5
   in when (x > 0) (return ())
```

### List comprehensions

Short

```haskell
map f xs = [f x | x <- xs]
```

Long

```haskell
defaultExtensions =
  [ e
  | EnableExtension {extensionField1 = extensionField1} <-
      knownExtensions knownExtensions
  , let a = b
    -- comment
  , let c = d
    -- comment
  ]
```

Another long one

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/357
foo =
  [ (x, y)
  | x <- [1 .. 10]
  , y <- [11 .. 20]
  , even x
  , even x
  , even x
  , even x
  , even x
  , odd y
  ]
```

With operators

```haskell
defaultExtensions =
  [e | e@EnableExtension {} <- knownExtensions]
    \\ map EnableExtension badExtensions
```

Transform list comprehensions

```haskell
list =
  [ (x, y, map the v)
  | x <- [1 .. 10]
  , y <- [1 .. 10]
  , let v = x + y
  , then group by v using groupWith
  , then take 10
  , then group using permutations
  , t <- concat v
  , then takeWhile by t < 3
  ]
```

#### Parallel list comprehensions

Short

```haskell
zip xs ys = [(x, y) | x <- xs | y <- ys]
```

Long

```haskell
fun xs ys =
  [ (alphaBetaGamma, deltaEpsilonZeta)
  | x <- xs
  , z <- zs
  | y <- ys
  , cond
  , let t = t
  ]
```

### Operators

With `do`

```haskell
a =
  for xs $ do
    left x
    right x
```

With lambda-case

```haskell
a =
  for xs $ \case
    Left x -> x
```

Qualified operator as an argument

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/273
foo = foldr1 (V.++) [V.empty, V.empty]
```

Apply an infix operator in prefix style

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/273
ys = (++) [] []
```

Qualified operator

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/273
xs = V.empty V.++ V.empty
```

In parentheses

```haskell
cat = (++)
```

Qualified operator in parentheses

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/273
cons = (V.++)
```

A list constructor enclosed by parentheses

```haskell
cons = (:)
```

A data constructor enclosed by parentheses

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/422
data T a =
  a :@ a

test = (:@)
```

Force indent and print RHS in a top-level expression

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/473
a =
  template
    $ haskell
        [ SomeVeryLongName
        , AnotherLongNameEvenLongToBreakTheLine
        , LastLongNameInList
        ]
```

#### Operator chains

Applicative style

```haskell
x =
  Value
    <$> thing
    <*> secondThing
    <*> thirdThing
    <*> fourthThing
    <*> Just thisissolong
    <*> Just stilllonger
    <*> evenlonger
```

`$` chain

```haskell
f =
  Right
    $ S.lazyByteStrings
    $ addPrefix prefix
    $ S.toLazyByteString
    $ prettyPrint m
```

Arithmetic operations

```haskell
f =
  aaaaaaaaaa * bbbbbbbbbbbbbb / cccccccccccccccccccccc
    + dddddddddddddd * eeeeeeeeeeeeeeee
    - ffffffffffffffff / -ggggggggggggg
```

Lens operators

```haskell
updateUsr usr =
  usr
    & userFirstName .~ "newfirst"
    & userLastName .~ "newlast"
    & userEmail .~ "newemail"
    & userPassword .~ "newpass"
```

### Primitive type values

`Char`

```haskell
a = 'a'
```

`\n` as a `Char`

```haskell
a = '\n'
```

`String` with a `\n`

```haskell
a = "bcd\nefgh"
```

Multiple line string

```haskell
foo =
  "hoge \
 \ fuga"
  where
    bar =
      "foo \
     \ bar"
```

Hex integers

```haskell
a = 0xa5
```

Unboxed integers

```haskell
{-# LANGUAGE MagicHash #-}

a = 0#
```

Unboxed floating point numbers

```haskell
{-# LANGUAGE MagicHash #-}

a = 3.3#
```

Unboxed `Char`

```haskell
{-# LANGUAGE MagicHash #-}

a = 'c'#
```

Unboxed `String`

```haskell
{-# LANGUAGE MagicHash #-}

a = "Foo"#
```

`UnboxedTuple`

```haskell
{-# LANGUAGE UnboxedTuples #-}

f :: (# Int, Int #) -> (# Int, Int #)
f t =
  case t of
    (# x, y #) -> (# x, y #)
```

`NumericUnderscores`

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/542
{-# LANGUAGE NumericUnderscores #-}

foo = 10_000
```

### Quasi-quotes

Body has multiple lines.

```haskell
{-# LANGUAGE QuasiQuotes #-}

f =
  [s|First line
Second line|]
```

Body has a top-level declaration.

```haskell
{-# LANGUAGE QuasiQuotes #-}

f =
  [d| f :: Int -> Int
      f = undefined |]
```

Typed quote.

```haskell
f = [||a||]
```

Preserve the trailing newline.

```haskell
{-# LANGUAGE QuasiQuotes #-}

f =
  [s|foo
|]
```

### Ranges

from

```haskell
a = [1 ..]
```

from to

```haskell
a = [1 .. 9]
```

from then

```haskell
b = [1,3 ..]
```

from then to

```haskell
c = [1,3 .. 9]
```

### Records

No fields

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/366
foo = Nothing {}
```

Short

```haskell
getGitProvider :: EventProvider GitRecord ()
getGitProvider =
  EventProvider {getModuleName = "Git", getEvents = getRepoCommits}
```

Medium

```haskell
commitToEvent :: FolderPath -> TimeZone -> Commit -> Event.Event
commitToEvent gitFolderPath timezone commit =
  Event.Event
    {pluginName = getModuleName getGitProvider, eventIcon = "glyphicon-cog"}
```

Long

```haskell
commitToEvent :: FolderPath -> TimeZone -> Commit -> Event.Event
commitToEvent gitFolderPath timezone commit =
  Event.Event
    { pluginName = getModuleName getGitProvider
    , eventIcon = "glyphicon-cog"
    , eventDate = localTimeToUTC timezone (commitDate commit)
    }
```

Another long one

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/358
foo =
  assert
    sanityCheck
    BomSnapshotAggr
      { snapshot = Just bs
      , previousId = M.bomSnapshotHistoryPreviousId . entityVal <$> bsp
      , nextId = M.bomSnapshotHistoryNextId . entityVal <$> bsn
      , bomEx = bx''
      , orderSubstitutes =
          S.fromList . map OrderSubstituteAggrByCreatedAtAsc $ subs
      , snapshotSubstitute = msub
      }
```

Record body may be in one line even if a new line is inserted after the variable name.

```haskell
addCommentsToNode mkNodeComment newComments nodeInfo@(NodeInfo (SrcSpanInfo _ _) existingComments) =
  nodeInfo
    {nodeInfoComments = existingComments <> map mkBeforeNodeComment newComments}
```

Symbol constructor

```haskell
f = (:..?) {}
```

Symbol field

```haskell
f x = x {(..?) = wat}

g x = Rec {(..?)}
```

A field updater in a `do` inside a `let ... in`.

```haskell
f = undefined
  where
    g h =
      let x = undefined
       in do
            foo
            pure
              h
                { grhssLocalBinds =
                    HsValBinds x (ValBinds (newSigs newSigMethods))
                }
```

`OverloadedRecordDot`

```haskell since 9.2.2
{-# LANGUAGE OverloadedRecordDot #-}

data Rectangle = Rectangle
  { width :: Int
  , height :: Int
  }

area :: Rectangle -> Int
area r = r.width * r.height

foo = (.x.y)
```

`OverloadedRecordUpdate`

```haskell since 9.2.0
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedRecordUpdate #-}

foo = bar {baz.qux = 1}
```

### Sections

With a LHS

```haskell
double = (2 *)
```

With a RHS

```haskell
halve = (/ 2)
```

With a large RHS

```haskell
foo =
  (`elem` concat
            [ [20, 68, 92, 112, 28, 124, 116, 80]
            , [21, 84, 87, 221, 127, 255, 241, 17]
            ])
```

## Template Haskell

Expression brackets

```haskell
add1 x = [|x + 1|]
```

Pattern brackets

```haskell
{-# LANGUAGE TemplateHaskell #-}

mkPat = [p|(x, y)|]
```

Type brackets

```haskell
{-# LANGUAGE TemplateHaskell #-}

foo :: $([t|Bool|]) -> a
```

A quoted TH name from a type name

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/412
{-# LANGUAGE TemplateHaskell #-}

data (-)

q = ''(-)
```

Quoted list constructors

```haskell
{-# LANGUAGE TemplateHaskell #-}

cons = '(:)
```

Pattern splices

```haskell
{-# LANGUAGE TemplateHaskell #-}

f $pat = ()

g =
  case x of
    $(mkPat y z) -> True
    _ -> False
```

Typed splice

```haskell
{-# LANGUAGE TemplateHaskell #-}

foo = $$bar
```

## Comments

Only comments

```haskell
-- foo
```

Double comments in a line

```haskell
f = undefined {- Comment 1 -} {- Comment 2 -} -- Comment 3
```

Comments within a declaration

```haskell
bob -- after bob
 =
  foo -- next to foo
  -- line after foo
    (bar
       foo -- next to bar foo
       bar -- next to bar
     ) -- next to the end paren of (bar)
    -- line after (bar)
    mu -- next to mu
    -- line after mu
    -- another line after mu
    zot -- next to zot
    -- line after zot
    (case casey -- after casey
           of
       Just -- after Just
        -> do
         justice -- after justice
           * foo
               (blah * blah
                  + z
                  + 2 / 4
                  + a
                  - -- before a line break
                   2
                     * -- inside this mess
                      z
                     / 2
                     / 2
                     / aooooo
                     / aaaaa -- bob comment
                )
           + (sdfsdfsd fsdfsdf) -- blah comment
         putStrLn "")
    [1, 2, 3]
    [ 1 -- foo
    , ( 2 -- bar
      , 2.5 -- mu
       )
    , 3
    ]
    -- in the end of the function
  where
    alpha = alpha
    -- between alpha and beta
    beta = beta
    -- after beta

foo = 1 -- after foo

gamma = do
  delta
  epsilon
  -- in the end of a do-block 1

gamma = do
  delta
  epsilon
  -- the very last block is detected differently
```

Comments in a do expression

```haskell
gamma = do
  -- in the beginning of a do-block
  delta
```

Comments in a class instance

```haskell
instance Pretty MatchForCase
  -- TODO: Do not forget to handle comments!
                                             where
  pretty' = undefined
```

Comments in a case expression

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/553
f x =
  case x of
    -- Bla bla
    Nothing -> 0
    Just y -> y
```

Haddock comments

```haskell
-- | Module comment.
module X where

-- | Main doc.
main :: IO ()
main = return ()

data X
  = X -- ^ X is for xylophone.
  | Y -- ^ Y is for why did I eat that pizza.

data X = X
  { field1 :: Int -- ^ Field1 is the first field.
  , field11 :: Char
    -- ^ This field comment is on its own line.
  , field2 :: Int -- ^ Field2 is the second field.
  , field3 :: Char -- ^ This is a long comment which starts next to
    -- the field but continues onto the next line, it aligns exactly
    -- with the field name.
  , field4 :: Char
    -- ^ This is a long comment which starts on the following line
    -- from from the field, lines continue at the sme column.
  }

foo ::
     String -- ^ Reason for eating pizza.
  -> Int -- ^ How many did you eat pizza?
  -> String -- ^ The report.
foo = undefined
```

Haddock for a class method

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/607
class Foo a where
  -- | Doc
  foo :: a
```

Module header with haddock comments

```haskell
-- | A module
module HIndent -- Foo
  ( -- * Formatting functions.
    reformat
  , -- * Testing
    test
  ) where
```

Comments around regular declarations

```haskell
-- This is some random comment.
-- | Main entry point.
main = putStrLn "Hello, World!"
-- This is another random comment.
```

Multi-line comments

```haskell
bob {- after bob -}
 =
  foo {- next to foo -}
  {- line after foo -}
    (bar
       foo {- next to bar foo -}
       bar {- next to bar -}
     ) {- next to the end paren of (bar) -}
    {- line after (bar) -}
    mu {- next to mu -}
    {- line after mu -}
    {- another line after mu -}
    zot {- next to zot -}
    {- line after zot -}
    (case casey {- after casey -}
           of
       Just {- after Just -}
        -> do
         justice {- after justice -}
           * foo
               (blah * blah
                  + z
                  + 2 / 4
                  + a
                  - {- before a line break -}
                   2
                     * {- inside this mess -}
                      z
                     / 2
                     / 2
                     / aooooo
                     / aaaaa {- bob comment -}
                )
           + (sdfsdfsd fsdfsdf) {- blah comment -}
         putStrLn "")
    [1, 2, 3]
    [ 1 {- foo -}
    , ( 2 {- bar -}
      , 2.5 {- mu -}
       )
    , 3
    ]

foo = 1 {- after foo -}
```

Multi-line comments with multi-line contents

```haskell
{- | This is some random comment.
Here is more docs and such.
Etc.
-}
main = putStrLn "Hello, World!"
{- This is another random comment. -}
```

Comments on functions in where clause

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/540
topLevelFunc1 = f
  where
    -- comment on func in where clause
    -- stays in the where clause
    f = undefined

topLevelFunc2 = f . g
    -- Another comment
  where
    {- multi
       line
       comment -}
    f = undefined -- single line comment
    -- single line comment
        -- Different size of indent
    g :: a
    g = undefined
```

Comments in a 'where' clause

```haskell
foo = undefined
  where
    bar
      -- A comment
     = undefined
      where
        a = b
    baz = undefined
```

Haddocks around data constructors

```haskell
data Foo
    -- | A haddock comment for 'Bar'.
  = Bar
    -- | A haddock comment for 'Baz'.
  | Baz
    -- | A haddock comment for 'Quuz'.
  | Quuz
```

## Identifiers

Unicode

```haskell
α = γ * "ω"
-- υ
```

`rec` and `mdo` are valid identifiers unless `RecursiveDo` is enabled

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/328
rec = undefined

mdo = undefined
```

The first character of an infix operator can be `@` unless `TypeApplications` is enabled.

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/421
a @: b = a + b

main = print (2 @: 2)
```

## Complex input

A complex, slow-to-print decl

```haskell
{-# LANGUAGE TemplateHaskell #-}

quasiQuotes =
  [ ( ''[]
    , \(typeVariable:_) _automaticPrinter ->
        (let presentVar = varE (presentVarName typeVariable)
          in lamE
               [varP (presentVarName typeVariable)]
               [|(let typeString = "[" ++ fst $(presentVar) ++ "]"
                   in ( typeString
                      , \xs ->
                          case fst $(presentVar) of
                            "GHC.Types.Char" ->
                              ChoicePresentation
                                "String"
                                [ ( "String"
                                  , StringPresentation
                                      "String"
                                      (concatMap
                                         getCh
                                         (map (snd $(presentVar)) xs)))
                                , ( "List of characters"
                                  , ListPresentation
                                      typeString
                                      (map (snd $(presentVar)) xs))
                                ]
                              where getCh (CharPresentation "GHC.Types.Char" ch) =
                                      ch
                                    getCh (ChoicePresentation _ ((_, CharPresentation _ ch):_)) =
                                      ch
                                    getCh _ = ""
                            _ ->
                              ListPresentation
                                typeString
                                (map (snd $(presentVar)) xs)))|]))
  ]
```

Random snippet from hindent itself

```haskell
exp' (App _ op a) = do
  (fits, st) <- fitsOnOneLine (spaced (map pretty (f : args)))
  if fits
    then put st
    else do
      pretty f
      newline
      spaces <- getIndentSpaces
      indented spaces (lined (map pretty args))
  where
    (f, args) = flatten op [a]
    flatten :: Exp NodeInfo -> [Exp NodeInfo] -> (Exp NodeInfo, [Exp NodeInfo])
    flatten (App _ f' a') b = flatten f' (a' : b)
    flatten f' as = (f', as)
```

Quasi quotes

```haskell
{-# LANGUAGE QuasiQuotes #-}

exp = [name|exp|]

f [qq|pattern|] = ()
```

## C preprocessor

Conditionals (`#if`)

```haskell
isDebug :: Bool
#if DEBUG
isDebug = True
#else
isDebug = False
#endif
```

Conditionals inside a `where` with empty lines and CPP

```haskell
-- https://github.com/mihaimaruseac/hindent/issues/779
foo = bar + baz
  where

#if 0
    bar = 1
    
    baz = 1
#else
    bar = 2
    
    baz = 2
#endif
```

Macro definitions (`#define`)

```haskell
#define STRINGIFY(x) #x
f = STRINGIFY (y)
```

Escaped newlines

```haskell
#define LONG_MACRO_DEFINITION \
  data Pair a b = Pair \
    { first :: a \
    , second :: b \
    }
#define SHORT_MACRO_DEFINITION \
  x
```

Language extensions are effective across CPP boundaries.

```haskell
{-# LANGUAGE PatternSynonyms #-}
#if 1
pattern Foo :: Int -> Bar
#else
pattern Foo :: Int -> Bar
#endif
```

## Literate Haskell

Code with `>`s

```haskell
> -- https://github.com/mihaimaruseac/hindent/issues/103
> foo :: a
> foo = undefined
```