Chapter 1
Parsing Haskell
How GHC turns a stream of characters into a syntax tree: the layout algorithm, a grammar that forbids its own ambiguities, and the trick that lets one production parse three different languages at once.
Where this lives in the tree
-
GHC/Parser/Lexer.xAlex lexer, the layout algorithm, and the P monad -
GHC/Parser.ythe Happy grammar, covering every piece of Haskell syntax -
GHC/Parser/PostProcess.hsresolves what the grammar deliberately left ambiguous -
GHC/Parser/Annotation.hsthe annotations that let GHC reprint your source exactly
Parsing is the phase people are most tempted to skip. It sounds like solved territory: a lexer, a grammar, a tree. But Haskell hands its parser two problems most languages never face: indentation that carries meaning, and a syntax so ambiguous that the parser genuinely cannot tell an expression from a pattern until long after it has read both. The way GHC solves them shapes everything downstream.
By the end of this phase GHC has a HsModule GhcPs: a syntax tree that mirrors
your source so faithfully it can be printed back out character for character,
comments and all. Nothing has been resolved, checked, or simplified. Every name
is still just a string in a namespace, and x + y is still three tokens rather
than an application of anything.
Two tools, two generated files
GHC does not hand-write its lexer or its parser. Both are generated:
GHC/Parser/Lexer.xis processed by Alex, which compiles regular expressions into a table-driven scanner.GHC/Parser.yis processed by Happy, which compiles a context-free grammar into an LALR shift-reduce parser.
Both files are large (the lexer runs to about 3,700 lines and the grammar to about 4,700), and both are mostly not regular expressions and productions. They are Haskell: the actions attached to each rule, plus a substantial preamble of supporting code. The generated tables are the small part.
The split matters more than it looks. A lexer that only recognised tokens could
be a pure function from String to [Token]. GHC’s cannot, because Haskell’s
layout rule means the tokens you emit depend on what you have already seen.
The parser monad
Both the lexer and the parser run in P, a state monad over PState:
newtype P a = P { unP :: PState -> ParseResult a }
PState carries what you would expect (the input StringBuffer, the current
location, accumulated warnings and errors) and a few things you might not:
data PState = PState {
buffer :: StringBuffer,
options :: ParserOpts,
warnings :: Messages PsMessage,
errors :: Messages PsMessage,
last_tk :: Strict.Maybe (PsLocated Token),
loc :: PsLoc, -- current loc (end of prev token + 1)
context :: [LayoutContext],
lex_state :: [Int],
...
Two fields there do the interesting work. context is the stack of open layout
contexts, which we will come back to. And last_tk, the last non-comment token,
exists because Haskell has a construct whose meaning depends on what preceded
it, which we will also come back to.
The result type is a small performance flourish worth noticing, because it tells you how hot this code is:
newtype ParseResult a = PR (# (# PState, a #) | PState #)
pattern POk :: PState -> a -> ParseResult a
pattern POk s a = PR (# (# s , a #) | #)
pattern PFailed :: PState -> ParseResult a
pattern PFailed s = PR (# | s #)
That is an unboxed sum, hidden behind pattern synonyms so the rest of the compiler can pretend it is an ordinary two-constructor data type. Success or failure costs no allocation at all. GHC uses its own extensions on itself, and the parser is one of the places it does so most aggressively.
Layout: where indentation becomes syntax
Haskell lets you write this:
greet name = case name of
Just n -> "hello, " ++ n
Nothing -> "hello"
and the language definition says it means this:
greet name = case name of { Just n -> "hello, " ++ n ; Nothing -> "hello" }
Somebody has to insert those braces and semicolons, and that somebody is the
lexer. When it emits a token that opens a block (where, let, do, of), it
switches into a dedicated start state and pushes a new layout context recording
the column the block began at:
data LayoutContext
= NoLayout
| Layout !Int !GenSemic
That Int is the reference column. Every subsequent line is compared against the
top of the context stack: start at the same column and you get a virtual
semicolon, start further left and the context is popped and you get a virtual
close brace. The tokens are called ITvocurly, ITvccurly and ITsemi
(virtual open and close curly), and they are what the grammar actually sees.
This is why the layout rule cannot live in the grammar. Happy sees a token stream in which the braces are already there; it never knows they were implied. And it is why the lexer needs state: the offside rule is a stack machine, not a regular language.
Whitespace, in a place you would not expect
Layout is the famous case of whitespace mattering. There is a second, subtler one. Consider:
f (!a) = ... -- a bang pattern: ! is a prefix operator here
g a ! b -- an infix operator application
The same character means different things depending on the spaces around it.
GHC’s rule, from the accepted proposal on whitespace-sensitive bang patterns,
classifies every operator occurrence into one of four categories by looking at
what sits immediately either side, which is exactly why PState bothers to
remember last_tk.
In accord with GHC Proposal #229 https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0229-whitespace-bang-patterns.rst we classify operator occurrences into four categories: a ! b -- a loose infix occurrence a!b -- a tight infix occurrence a !b -- a prefix occurrence a! b -- a suffix occurrence The rules are a bit more elaborate than simply checking for whitespace, in order to accommodate the following use cases: f (!a) = ... -- prefix occurrence g (a !) -- loose infix occurrence g (! a) -- loose infix occurrence The precise rules are as follows: * Identifiers, literals, and opening brackets (, (#, (|, [, [|, [||, [p|, [e|, [t|, {, ⟦, ⦇, are considered "opening tokens". The function followedByOpeningToken tests whether the next token is an opening token. * Identifiers, literals, and closing brackets ), #), |), ], |], }, ⟧, ⦈, are considered "closing tokens". The function precededByClosingToken tests whether the previous token is a closing token. * Whitespace, comments, separators, and other tokens, are considered neither opening nor closing. * Any unqualified operator occurrence is classified as prefix, suffix, or tight/loose infix, based on preceding and following tokens: precededByClosingToken | followedByOpeningToken | Occurrence ------------------------+------------------------+------------ False | True | prefix True | False | suffix True | True | tight infix False | False | loose infix ------------------------+------------------------+------------ A loose infix occurrence is always considered an operator. Other types of
Show the rest of this Note (79 more lines)
occurrences may be assigned a special per-operator meaning override:
Operator | Occurrence | Token returned
----------+---------------+------------------------------------------
! | prefix | ITbang
| | strictness annotation or bang pattern,
| | e.g. f !x = rhs, data T = MkT !a
| not prefix | ITvarsym "!"
| | ordinary operator or type operator,
| | e.g. xs ! 3, (! x), Int ! Bool
----------+---------------+------------------------------------------
~ | prefix | ITtilde
| | laziness annotation or lazy pattern,
| | e.g. f ~x = rhs, data T = MkT ~a
| not prefix | ITvarsym "~"
| | ordinary operator or type operator,
| | e.g. xs ~ 3, (~ x), Int ~ Bool
----------+---------------+------------------------------------------
. | prefix | ITproj True
| | field projection,
| | e.g. .x
| tight infix | ITproj False
| | field projection,
| | e.g. r.x
| suffix | ITdot
| | function composition,
| | e.g. f. g
| loose infix | ITdot
| | function composition,
| | e.g. f . g
----------+---------------+------------------------------------------
$ $$ | prefix | ITdollar, ITdollardollar
| | untyped or typed Template Haskell splice,
| | e.g. $(f x), $$(f x), $$"str"
| not prefix | ITvarsym "$", ITvarsym "$$"
| | ordinary operator or type operator,
| | e.g. f $ g x, a $$ b
----------+---------------+------------------------------------------
@ | prefix | ITtypeApp
| | type application, e.g. fmap @Maybe
| tight infix | ITat
| | as-pattern, e.g. f p@(a,b) = rhs
| suffix | parse error
| | e.g. f p@ x = rhs
| loose infix | ITvarsym "@"
| | ordinary operator or type operator,
| | e.g. f @ g, (f @)
----------+---------------+------------------------------------------
Also, some of these overrides are guarded behind language extensions.
According to the specification, we must determine the occurrence based on
surrounding *tokens* (see the proposal for the exact rules). However, in
the implementation we cheat a little and do the classification based on
characters, for reasons of both simplicity and efficiency (see
'followedByOpeningToken' and 'precededByClosingToken')
When an operator is subject to a meaning override, it is mapped to special
token: ITbang, ITtilde, ITat, ITdollar, ITdollardollar. Otherwise, it is
returned as ITvarsym.
For example, this is how we process the (!):
precededByClosingToken | followedByOpeningToken | Token
------------------------+------------------------+-------------
False | True | ITbang
True | False | ITvarsym "!"
True | True | ITvarsym "!"
False | False | ITvarsym "!"
------------------------+------------------------+-------------
And this is how we process the (@):
precededByClosingToken | followedByOpeningToken | Token
------------------------+------------------------+-------------
False | True | ITtypeApp
True | False | parse error
True | True | ITat
False | False | ITvarsym "@"
------------------------+------------------------+------------- The table in the middle of that Note is the whole rule. a ! b and a!b are
both infix; a !b is prefix and a! b is suffix. Only then does GHC consult a
per-operator override to decide which token to emit: ! in prefix position
becomes ITbang, a strictness annotation, while a loose infix ! stays an
ordinary operator.
A grammar that forbids its own ambiguities
Shift-reduce parsers have a characteristic failure mode: a state where the parser could either push the next token or reduce what it already has, and the choice changes the parse. Happy resolves these silently by default, which is a reasonable thing for a parser generator to do and a terrible thing for a language whose behaviour is a specification.
So Parser.y declares, near the top:
%expect 0
Zero unresolved shift-reduce conflicts. Every genuine ambiguity in Haskell’s grammar must be resolved explicitly, and the file documents each one. The canonical worked example is in the grammar’s own preamble:
The 'happy' tool turns this grammar into an efficient parser that follows the
shift-reduce parsing model. There's a parse stack that contains items parsed so
far (both terminals and non-terminals). Every next token produced by the lexer
results in one of two actions:
SHIFT: push the token onto the parse stack
REDUCE: pop a few items off the parse stack and combine them
with a function (reduction rule)
However, sometimes it's unclear which of the two actions to take.
Consider this code example:
if x then y else f z
There are two ways to parse it:
(if x then y else f) z
if x then y else (f z)
How is this determined? At some point, the parser gets to the following state:
parse stack: 'if' exp 'then' exp 'else' "f"
next token: "z"
Scenario A (simplified):
1. REDUCE, parse stack: 'if' exp 'then' exp 'else' exp
next token: "z"
(Note that "f" reduced to exp here)
2. REDUCE, parse stack: exp
next token: "z"
3. SHIFT, parse stack: exp "z"
next token: ...
4. REDUCE, parse stack: exp
next token: ...
This way we get: (if x then y else f) z
Scenario B (simplified):
Show the rest of this Note (84 more lines)
1. SHIFT, parse stack: 'if' exp 'then' exp 'else' "f" "z"
next token: ...
2. REDUCE, parse stack: 'if' exp 'then' exp 'else' exp
next token: ...
3. REDUCE, parse stack: exp
next token: ...
This way we get: if x then y else (f z)
The end result is determined by the chosen action. When Happy detects this, it
reports a shift/reduce conflict. At the top of the file, we have the following
directive:
%expect 0
It means that we expect no unresolved shift/reduce conflicts in this grammar.
If you modify the grammar and get shift/reduce conflicts, follow the steps
below to resolve them.
STEP ONE
is to figure out what causes the conflict.
That's where the -i flag comes in handy:
happy -agc --strict compiler/GHC/Parser.y -idetailed-info
By analysing the output of this command, in a new file `detailed-info`, you
can figure out which reduction rule causes the issue. At the top of the
generated report, you will see a line like this:
state 147 contains 67 shift/reduce conflicts.
Scroll down to section State 147 (in your case it could be a different
state). The start of the section lists the reduction rules that can fire
and shows their context:
exp10 -> fexp . (rule 492)
fexp -> fexp . aexp (rule 498)
fexp -> fexp . PREFIX_AT atype (rule 499)
And then, for every token, it tells you the parsing action:
']' reduce using rule 492
'::' reduce using rule 492
'(' shift, and enter state 178
QVARID shift, and enter state 44
DO shift, and enter state 182
...
But if you look closer, some of these tokens also have another parsing action
in parentheses:
QVARID shift, and enter state 44
(reduce using rule 492)
That's how you know rule 492 is causing trouble.
Scroll back to the top to see what this rule is:
Grammar
...
...
exp10 -> fexp (492)
optSemi -> ';' (493)
...
...
Hence the shift/reduce conflict is caused by this parser production:
exp10 :: { ECP }
: '-' fexp { ... }
| fexp { ... } -- problematic rule
STEP TWO
is to mark the problematic rule with the %shift pragma. This signals to
'happy' that any shift/reduce conflicts involving this rule must be resolved
in favor of a shift. There's currently no dedicated pragma to resolve in
favor of the reduce.
STEP THREE
is to add a dedicated Note for this specific conflict, as is done for all
other conflicts below. Search the grammar for %shift and you will find the individual resolutions,
each with its own Note: %shift: exp10 -> fexp, %shift: type -> btype, and a
dozen more. They are among the most narrowly-scoped comments in GHC, and they
exist because a future contributor will perturb the grammar and need to know
which conflicts were deliberate.
When the grammar genuinely cannot decide
Conflicts you can resolve with a precedence declaration are the easy case. Haskell also has ambiguities that no amount of lookahead will fix, because the disambiguating token can be arbitrarily far away:
f (Con a b ) = ... -- 'Con a b' is a pattern
f (Con a b -> x) = ... -- 'Con a b' is an expression
Until the parser reaches -> or =, it cannot know which language it is reading.
The same shape recurs in do blocks, in guards, and (with a third possibility,
arrow commands) inside proc.
The obvious fixes are all bad. Parsing both and backtracking is expensive and Happy will not do it. Parsing into a union type means every downstream consumer handles cases that cannot occur. Duplicating the grammar triples it.
GHC’s answer is to make the production polymorphic in what it is building:
There are places in the grammar where we do not know whether we are parsing an
expression or a pattern without unlimited lookahead (which we do not have in
'happy'):
View patterns:
f (Con a b ) = ... -- 'Con a b' is a pattern
f (Con a b -> x) = ... -- 'Con a b' is an expression
do-notation:
do { Con a b <- x } -- 'Con a b' is a pattern
do { Con a b } -- 'Con a b' is an expression
Guards:
x | True <- p && q = ... -- 'True' is a pattern
x | True = ... -- 'True' is an expression
Top-level value/function declarations (FunBind/PatBind):
f ! a -- TH splice
f ! a = ... -- function declaration
Until we encounter the = sign, we don't know if it's a top-level
TemplateHaskell splice where ! is used, or if it's a function declaration
where ! is bound.
There are also places in the grammar where we do not know whether we are
parsing an expression or a command:
proc x -> do { (stuff) -< x } -- 'stuff' is an expression
proc x -> do { (stuff) } -- 'stuff' is a command
Until we encounter arrow syntax (-<) we don't know whether to parse 'stuff'
as an expression or a command.
In fact, do-notation is subject to both ambiguities:
proc x -> do { (stuff) -< x } -- 'stuff' is an expression
proc x -> do { (stuff) <- f -< x } -- 'stuff' is a pattern
proc x -> do { (stuff) } -- 'stuff' is a command
There are many possible solutions to this problem. For an overview of the ones
we decided against, see Note [Resolving parsing ambiguities: non-taken alternatives]
The solution that keeps basic definitions (such as HsExpr) clean, keeps the
concerns local to the parser, and does not require duplication of hsSyn types, Show the rest of this Note (61 more lines)
or an extra pass over the entire AST, is to parse into an overloaded
parser-validator (a so-called tagless final encoding):
class DisambECP b where ...
instance DisambECP (HsCmd GhcPs) where ...
instance DisambECP (HsExp GhcPs) where ...
instance DisambECP (PatBuilder GhcPs) where ...
The 'DisambECP' class contains functions to build and validate 'b'. For example,
to add parentheses we have:
mkHsParPV :: DisambECP b => SrcSpan -> Located b -> PV (Located b)
'mkHsParPV' will wrap the inner value in HsCmdPar for commands, HsPar for
expressions, and 'PatBuilderPar' for patterns (later transformed into ParPat,
see Note [PatBuilder]).
Consider the 'alts' production used to parse case-of alternatives:
alts :: { Located ([AddEpAnn],[LMatch GhcPs (LHsExpr GhcPs)]) }
: alts1 { sL1 $1 (fst $ unLoc $1,snd $ unLoc $1) }
| ';' alts { sLL $1 $> ((mj AnnSemi $1:(fst $ unLoc $2)),snd $ unLoc $2) }
We abstract over LHsExpr GhcPs, and it becomes:
alts :: { forall b. DisambECP b => PV (Located ([AddEpAnn],[LMatch GhcPs (Located b)])) }
: alts1 { $1 >>= \ $1 ->
return $ sL1 $1 (fst $ unLoc $1,snd $ unLoc $1) }
| ';' alts { $2 >>= \ $2 ->
return $ sLL $1 $> ((mj AnnSemi $1:(fst $ unLoc $2)),snd $ unLoc $2) }
Compared to the initial definition, the added bits are:
forall b. DisambECP b => PV ( ... ) -- in the type signature
$1 >>= \ $1 -> return $ -- in one reduction rule
$2 >>= \ $2 -> return $ -- in another reduction rule
The overhead is constant relative to the size of the rest of the reduction
rule, so this approach scales well to large parser productions.
Note that we write ($1 >>= \ $1 -> ...), so the second $1 is in a binding
position and shadows the previous $1. We can do this because internally
'happy' desugars $n to happy_var_n, and the rationale behind this idiom
is to be able to write (sLL $1 $>) later on. The alternative would be to
write this as ($1 >>= \ fresh_name -> ...), but then we couldn't refer
to the last fresh name as $>.
Finally, we instantiate the polymorphic type to a concrete one, and run the
parser-validator, for example:
stmt :: { forall b. DisambECP b => PV (LStmt GhcPs (Located b)) }
e_stmt :: { LStmt GhcPs (LHsExpr GhcPs) }
: stmt {% runPV $1 }
In e_stmt, three things happen:
1. we instantiate: b ~ HsExpr GhcPs
2. we embed the PV computation into P by using runPV
3. we run validation by using a monadic production, {% ... }
At this point the ambiguity is resolved. This is a tagless-final encoding. A single grammar production is written against
the DisambECP class, and the instance chosen at the call site decides whether
the result is an expression, a command, or a pattern. One production, three
languages, no backtracking and no union type, at the cost of a layer of
indirection that makes PostProcess.hs one of the harder files in the front end
to read cold.
Nothing is thrown away
A parser that only needed to feed a compiler could discard comments, forget
whether you wrote (a, b) or ( a , b ), and normalise away the parentheses it
no longer needs. GHC cannot, because the same tree is used by tooling (HLint,
Ormolu, ghc-exactprint, IDEs) that has to reproduce your source exactly.
Given a parse tree of a Haskell module, how can we reconstruct the original Haskell source code, retaining all whitespace and source code comments? We need to track the locations of all elements from the original source: this includes keywords such as 'let' / 'in' / 'do' etc as well as punctuation such as commas and braces, and also comments. We collectively refer to this metadata as the "exact print annotations". NON-COMMENT ELEMENTS Intuitively, every AST element directly contains a bag of keywords (keywords can show up more than once in a node: a semicolon i.e. newline can show up multiple times before the next AST element), each of which needs to be associated with its location in the original source code. These keywords are recorded directly in the AST element in which they occur, for the GhcPs phase. For any given element in the AST, there is only a set number of keywords that are applicable for it (e.g., you'll never see an 'import' keyword associated with a let-binding.) The set of allowed keywords is documented in a comment associated with the constructor of a given AST element, although the ground truth is in GHC.Parser and GHC.Parser.PostProcess (which actually add the annotations). COMMENT ELEMENTS We associate comments with the lowest (most specific) AST element enclosing them
Show the rest of this Note (49 more lines)
PARSER STATE There are three fields in PState (the parser state) which play a role with annotation comments. > comment_q :: [LEpaComment], > header_comments :: Maybe [LEpaComment], > eof_pos :: Maybe (RealSrcSpan, RealSrcSpan), -- pos, gap to prior token The 'comment_q' field captures comments as they are seen in the token stream, so that when they are ready to be allocated via the parser they are available. The 'header_comments' capture the comments coming at the top of the source file. They are moved there from the `comment_q` when comments are allocated for the first top-level declaration. The 'eof_pos' captures the final location in the file, and the location of the immediately preceding token to the last location, so that the exact-printer can work out how far to advance to add the trailing whitespace. PARSER EMISSION OF ANNOTATIONS The parser interacts with the lexer using the functions > getCommentsFor :: (MonadP m) => SrcSpan -> m EpAnnComments > getPriorCommentsFor :: (MonadP m) => SrcSpan -> m EpAnnComments > getFinalCommentsFor :: (MonadP m) => SrcSpan -> m EpAnnComments The 'getCommentsFor' function is the one used most often. It takes the AST element SrcSpan and removes and returns any comments in the 'comment_q' that are inside the span. 'allocateComments' in 'Lexer' is responsible for making sure we only return comments that actually fit in the 'SrcSpan'. The 'getPriorCommentsFor' function is used for top-level declarations, and removes and returns any comments in the 'comment_q' that either precede or are included in the given SrcSpan. This is to ensure that preceding documentation comments are kept together with the declaration they belong to. The 'getFinalCommentsFor' function is called right at the end when EOF is hit. This drains the 'comment_q' completely, and returns the 'header_comments', remaining 'comment_q' entries and the 'eof_pos'. These values are inserted into the 'HsModule' AST element. The wiki page describing this feature is https://gitlab.haskell.org/ghc/ghc/wikis/api-annotations
So the tree carries the source span of every keyword, bracket and comma, plus the comments and where they attached. This is a large part of why the parsed AST dump below is so much bigger than the program that produced it.
Seeing it happen
Here is a small module exercising layout, an operator section, a user-defined
infix operator, and do notation. Step through the stages: the first two tabs
are what this chapter produced.
What you wrote.
-- | A deliberately small module aimed at the *front* of the pipeline.
--
-- The point of interest here is the parsed AST rather than the Core: layout
-- (no braces or semicolons are written, yet the parser inserts them),
-- operator sections, `do` notation, and an infix operator whose fixity is not
-- known until the renamer runs.
module Syntax where
infixl 6 |+|
(|+|) :: Int -> Int -> Int
x |+| y = x + y * 2
total :: [Int] -> Int
total xs = sum (map (|+| 1) xs)
greet :: Maybe String -> String
greet name = case name of
Just n -> "hello, " ++ n
Nothing -> "hello"
collect :: [Int] -> [Int]
collect xs = do
x <- xs
let doubled = x * 2
pure doubledThe raw syntax tree, including the annotations that let GHC reprint your source exactly as written.
(L
{ examples/Syntax.hs:1:1 }
(HsModule
(XModulePs
(EpAnn
(EpaSpan { examples/Syntax.hs:1:1 })
(AnnsModule
(NoEpTok)
(EpTok
(EpaSpan { examples/Syntax.hs:7:1-6 }))
(EpTok
(EpaSpan { examples/Syntax.hs:7:15-19 }))
[]
[]
(Just
((,)
{ examples/Syntax.hs:27:1 }
{ examples/Syntax.hs:26:8-14 })))
(EpaCommentsBalanced
[]
[]))
(EpVirtualBraces
(1))
(Nothing)
(Nothing))
(Just
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:7:8-13 })
(AnnListItem
[])
(EpaComments
[]))
{ModuleName: Syntax}))
(Nothing)
[]
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:9:1-12 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(FixSig
((,)
((,)
(EpaSpan { examples/Syntax.hs:9:1-6 })
(Just
(EpaSpan { examples/Syntax.hs:9:8 })))
(SourceText 6))
(FixitySig
(NoNamespaceSpecifier)
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:9:10-12 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))]
(Fixity
(6)
(InfixL))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:1-26 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:11:7-8 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:1-5 })
(NameAnn
(NameParens
(EpTok
(EpaSpan { examples/Syntax.hs:11:1 }))
(EpTok
(EpaSpan { examples/Syntax.hs:11:5 })))
(EpaSpan { examples/Syntax.hs:11:2-4 })
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:11:14-15 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-12 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-12 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:17-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:11:21-22 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:17-19 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:17-19 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:24-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:24-26 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1-19 })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:3-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1-19 })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1-19 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:3-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))
(Infix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:12:1-7 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:7 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: y}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:9-19 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:12:9-19 })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:12:9 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11-19 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11-15 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:13 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: +}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:15 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:15 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: y}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:17 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:17 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: *}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:19 })
(AnnListItem
[])
(EpaComments
[]))
(HsOverLit
(NoExtField)
(OverLit
(NoExtField)
(HsIntegral
(IL
(SourceText 2)
(False)
(2))))))))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:1-21 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:14:7-8 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: total}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:10-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:10-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:14:16-17 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:10-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsListTy
(AnnParensSquare
(EpTok
(EpaSpan { examples/Syntax.hs:14:10 }))
(EpTok
(EpaSpan { examples/Syntax.hs:14:14 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:11-13 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:11-13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:19-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:19-21 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-31 })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: total}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-31 })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-31 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: total}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:15:7-8 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:7-8 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:7-8 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:10-31 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:15:10-31 })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:15:10 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:12-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:12-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:12-14 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: sum}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:16-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsPar
((,)
(EpTok
(EpaSpan { examples/Syntax.hs:15:16 }))
(EpTok
(EpaSpan { examples/Syntax.hs:15:31 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-30 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-27 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-19 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-19 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: map}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:21-27 })
(AnnListItem
[])
(EpaComments
[]))
(HsPar
((,)
(EpTok
(EpaSpan { examples/Syntax.hs:15:21 }))
(EpTok
(EpaSpan { examples/Syntax.hs:15:27 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:22-26 })
(AnnListItem
[])
(EpaComments
[]))
(SectionR
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:22-24 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:22-24 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:26 })
(AnnListItem
[])
(EpaComments
[]))
(HsOverLit
(NoExtField)
(OverLit
(NoExtField)
(HsIntegral
(IL
(SourceText 1)
(False)
(1))))))))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:29-30 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:29-30 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))))))))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:1-31 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:17:7-8 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: greet}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:17:23-24 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsAppTy
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-14 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Maybe}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:16-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:16-21 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: String}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:26-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:26-31 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: String}))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,1)-(20,20) })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: greet}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,1)-(20,20) })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,1)-(20,20) })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: greet}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:18:7-10 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:7-10 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:7-10 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: name}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,12)-(20,20) })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,12)-(20,20) })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:18:12 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,14)-(20,20) })
(AnnListItem
[])
(EpaComments
[]))
(HsCase
(EpAnnHsCase
(EpTok
(EpaSpan { examples/Syntax.hs:18:14-17 }))
(EpTok
(EpaSpan { examples/Syntax.hs:18:24-25 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:19-22 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:19-22 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: name}))))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(19,3)-(20,20) })
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:(19,3)-(20,20) }))
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:3-26 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(CaseAlt)
(L
(EpaSpan { examples/Syntax.hs:19:3-8 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:3-8 })
(AnnListItem
[])
(EpaComments
[]))
(ConPat
((,)
(Nothing)
(Nothing))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:3-6 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Just}))
(PrefixCon
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:8 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:8 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: n}))))])))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:10-26 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:19:10-26 })
(GrhsAnn
(Nothing)
(Right
(EpUniTok
(EpaSpan { examples/Syntax.hs:19:10-11 })
(NormalSyntax))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:13-26 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:13-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsLit
(NoExtField)
(HsString
(SourceText "hello, ")
{FastString: "hello, "})))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:23-24 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:23-24 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: ++}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:26 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:26 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: n}))))))))
[])
(EmptyLocalBinds
(NoExtField)))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:3-20 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(CaseAlt)
(L
(EpaSpan { examples/Syntax.hs:20:3-9 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:3-9 })
(AnnListItem
[])
(EpaComments
[]))
(ConPat
((,)
(Nothing)
(Nothing))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:3-9 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Nothing}))
(PrefixCon
[])))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:11-20 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:20:11-20 })
(GrhsAnn
(Nothing)
(Right
(EpUniTok
(EpaSpan { examples/Syntax.hs:20:11-12 })
(NormalSyntax))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:14-20 })
(AnnListItem
[])
(EpaComments
[]))
(HsLit
(NoExtField)
(HsString
(SourceText "hello")
{FastString: "hello"})))))
[])
(EmptyLocalBinds
(NoExtField)))))]))))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:1-25 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:22:9-10 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:1-7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: collect}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:12-25 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:12-25 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:22:18-19 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:12-16 })
(AnnListItem
[])
(EpaComments
[]))
(HsListTy
(AnnParensSquare
(EpTok
(EpaSpan { examples/Syntax.hs:22:12 }))
(EpTok
(EpaSpan { examples/Syntax.hs:22:16 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:13-15 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:13-15 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:21-25 })
(AnnListItem
[])
(EpaComments
[]))
(HsListTy
(AnnParensSquare
(EpTok
(EpaSpan { examples/Syntax.hs:22:21 }))
(EpTok
(EpaSpan { examples/Syntax.hs:22:25 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:22-24 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:22-24 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,1)-(26,14) })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:1-7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: collect}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,1)-(26,14) })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,1)-(26,14) })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:1-7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: collect}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:23:9-10 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:9-10 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:9-10 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,12)-(26,14) })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,12)-(26,14) })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:23:12 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,14)-(26,14) })
(AnnListItem
[])
(EpaComments
[]))
(HsDo
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:(24,3)-(26,14) }))
(ListNone)
[]
(EpaSpan { examples/Syntax.hs:23:14-15 })
[])
(DoExpr
(Nothing))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(24,3)-(26,14) })
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:(24,3)-(26,14) }))
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:3-9 })
(AnnListItem
[])
(EpaComments
[]))
(BindStmt
(EpUniTok
(EpaSpan { examples/Syntax.hs:24:5-6 })
(NormalSyntax))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:3 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:3 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:8-9 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:8-9 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:3-21 })
(AnnListItem
[])
(EpaComments
[]))
(LetStmt
(EpTok
(EpaSpan { examples/Syntax.hs:25:3-5 }))
(HsValBinds
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:25:7-21 }))
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
(ValBinds
(NoAnnSortKey)
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnListItem
[])
(EpaComments
[]))
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: doubled}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: doubled}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { <no location info> })
[])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:15-21 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:25:15-21 })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:25:15 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:17-21 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:17 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:17 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:19 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:19 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: *}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:21 })
(AnnListItem
[])
(EpaComments
[]))
(HsOverLit
(NoExtField)
(OverLit
(NoExtField)
(HsIntegral
(IL
(SourceText 2)
(False)
(2))))))))))
[])
(EmptyLocalBinds
(NoExtField)))))]))))]
[]))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-14 })
(AnnListItem
[])
(EpaComments
[]))
(BodyStmt
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-6 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-6 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: pure}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:8-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:8-14 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: doubled}))))))
(NoExtField)
(NoExtField)))])))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))]))(L
{ examples/Syntax.hs:1:1 }
(HsModule
(XModulePs
(EpAnn
(EpaSpan { examples/Syntax.hs:1:1 })
(AnnsModule
(NoEpTok)
(EpTok
(EpaSpan { examples/Syntax.hs:7:1-6 }))
(EpTok
(EpaSpan { examples/Syntax.hs:7:15-19 }))
[]
[]
(Just
((,)
{ examples/Syntax.hs:27:1 }
{ examples/Syntax.hs:26:8-14 })))
(EpaCommentsBalanced
[]
[]))
(EpVirtualBraces
(1))
(Nothing)
(Nothing))
(Just
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:7:8-13 })
(AnnListItem
[])
(EpaComments
[]))
{ModuleName: Syntax}))
(Nothing)
[]
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:9:1-12 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(FixSig
((,)
((,)
(EpaSpan { examples/Syntax.hs:9:1-6 })
(Just
(EpaSpan { examples/Syntax.hs:9:8 })))
(SourceText 6))
(FixitySig
(NoNamespaceSpecifier)
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:9:10-12 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))]
(Fixity
(6)
(InfixL))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:1-26 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:11:7-8 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:1-5 })
(NameAnn
(NameParens
(EpTok
(EpaSpan { examples/Syntax.hs:11:1 }))
(EpTok
(EpaSpan { examples/Syntax.hs:11:5 })))
(EpaSpan { examples/Syntax.hs:11:2-4 })
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:11:14-15 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-12 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:10-12 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:17-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:11:21-22 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:17-19 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:17-19 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:24-26 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:11:24-26 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1-19 })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:3-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1-19 })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1-19 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:3-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))
(Infix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:12:1-7 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:1 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:7 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: y}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:9-19 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:12:9-19 })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:12:9 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11-19 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11-15 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:11 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:13 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: +}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:15 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:15 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: y}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:17 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:17 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: *}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:12:19 })
(AnnListItem
[])
(EpaComments
[]))
(HsOverLit
(NoExtField)
(OverLit
(NoExtField)
(HsIntegral
(IL
(SourceText 2)
(False)
(2))))))))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:1-21 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:14:7-8 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: total}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:10-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:10-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:14:16-17 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:10-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsListTy
(AnnParensSquare
(EpTok
(EpaSpan { examples/Syntax.hs:14:10 }))
(EpTok
(EpaSpan { examples/Syntax.hs:14:14 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:11-13 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:11-13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:19-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:14:19-21 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-31 })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: total}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-31 })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-31 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: total}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:15:7-8 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:7-8 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:7-8 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:10-31 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:15:10-31 })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:15:10 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:12-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:12-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:12-14 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: sum}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:16-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsPar
((,)
(EpTok
(EpaSpan { examples/Syntax.hs:15:16 }))
(EpTok
(EpaSpan { examples/Syntax.hs:15:31 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-30 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-27 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-19 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:17-19 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: map}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:21-27 })
(AnnListItem
[])
(EpaComments
[]))
(HsPar
((,)
(EpTok
(EpaSpan { examples/Syntax.hs:15:21 }))
(EpTok
(EpaSpan { examples/Syntax.hs:15:27 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:22-26 })
(AnnListItem
[])
(EpaComments
[]))
(SectionR
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:22-24 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:22-24 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: |+|}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:26 })
(AnnListItem
[])
(EpaComments
[]))
(HsOverLit
(NoExtField)
(OverLit
(NoExtField)
(HsIntegral
(IL
(SourceText 1)
(False)
(1))))))))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:29-30 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:15:29-30 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))))))))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:1-31 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:17:7-8 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: greet}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:17:23-24 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsAppTy
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:10-14 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Maybe}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:16-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:16-21 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: String}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:26-31 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:17:26-31 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: String}))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,1)-(20,20) })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: greet}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,1)-(20,20) })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,1)-(20,20) })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:1-5 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: greet}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:18:7-10 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:7-10 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:7-10 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: name}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,12)-(20,20) })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,12)-(20,20) })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:18:12 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(18,14)-(20,20) })
(AnnListItem
[])
(EpaComments
[]))
(HsCase
(EpAnnHsCase
(EpTok
(EpaSpan { examples/Syntax.hs:18:14-17 }))
(EpTok
(EpaSpan { examples/Syntax.hs:18:24-25 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:19-22 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:18:19-22 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: name}))))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(19,3)-(20,20) })
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:(19,3)-(20,20) }))
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:3-26 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(CaseAlt)
(L
(EpaSpan { examples/Syntax.hs:19:3-8 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:3-8 })
(AnnListItem
[])
(EpaComments
[]))
(ConPat
((,)
(Nothing)
(Nothing))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:3-6 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Just}))
(PrefixCon
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:8 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:8 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: n}))))])))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:10-26 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:19:10-26 })
(GrhsAnn
(Nothing)
(Right
(EpUniTok
(EpaSpan { examples/Syntax.hs:19:10-11 })
(NormalSyntax))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:13-26 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:13-21 })
(AnnListItem
[])
(EpaComments
[]))
(HsLit
(NoExtField)
(HsString
(SourceText "hello, ")
{FastString: "hello, "})))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:23-24 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:23-24 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: ++}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:26 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:19:26 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: n}))))))))
[])
(EmptyLocalBinds
(NoExtField)))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:3-20 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(CaseAlt)
(L
(EpaSpan { examples/Syntax.hs:20:3-9 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:3-9 })
(AnnListItem
[])
(EpaComments
[]))
(ConPat
((,)
(Nothing)
(Nothing))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:3-9 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Nothing}))
(PrefixCon
[])))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:11-20 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:20:11-20 })
(GrhsAnn
(Nothing)
(Right
(EpUniTok
(EpaSpan { examples/Syntax.hs:20:11-12 })
(NormalSyntax))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:20:14-20 })
(AnnListItem
[])
(EpaComments
[]))
(HsLit
(NoExtField)
(HsString
(SourceText "hello")
{FastString: "hello"})))))
[])
(EmptyLocalBinds
(NoExtField)))))]))))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:1-25 })
(AnnListItem
[])
(EpaComments
[]))
(SigD
(NoExtField)
(TypeSig
(AnnSig
(EpUniTok
(EpaSpan { examples/Syntax.hs:22:9-10 })
(NormalSyntax))
(Nothing)
(Nothing))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:1-7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: collect}))]
(HsWC
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:12-25 })
(AnnListItem
[])
(EpaComments
[]))
(HsSig
(NoExtField)
(HsOuterImplicit
(NoExtField))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:12-25 })
(AnnListItem
[])
(EpaComments
[]))
(HsFunTy
(NoExtField)
(HsUnannotated
(EpArrow
(EpUniTok
(EpaSpan { examples/Syntax.hs:22:18-19 })
(NormalSyntax))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:12-16 })
(AnnListItem
[])
(EpaComments
[]))
(HsListTy
(AnnParensSquare
(EpTok
(EpaSpan { examples/Syntax.hs:22:12 }))
(EpTok
(EpaSpan { examples/Syntax.hs:22:16 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:13-15 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:13-15 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:21-25 })
(AnnListItem
[])
(EpaComments
[]))
(HsListTy
(AnnParensSquare
(EpTok
(EpaSpan { examples/Syntax.hs:22:21 }))
(EpTok
(EpaSpan { examples/Syntax.hs:22:25 })))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:22-24 })
(AnnListItem
[])
(EpaComments
[]))
(HsTyVar
(NoEpTok)
(NotPromoted)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:22:22-24 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: Int}))))))))))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,1)-(26,14) })
(AnnListItem
[])
(EpaComments
[]))
(ValD
(NoExtField)
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:1-7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: collect}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,1)-(26,14) })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,1)-(26,14) })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:1-7 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: collect}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { examples/Syntax.hs:23:9-10 })
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:9-10 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:23:9-10 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,12)-(26,14) })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,12)-(26,14) })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:23:12 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(23,14)-(26,14) })
(AnnListItem
[])
(EpaComments
[]))
(HsDo
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:(24,3)-(26,14) }))
(ListNone)
[]
(EpaSpan { examples/Syntax.hs:23:14-15 })
[])
(DoExpr
(Nothing))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:(24,3)-(26,14) })
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:(24,3)-(26,14) }))
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:3-9 })
(AnnListItem
[])
(EpaComments
[]))
(BindStmt
(EpUniTok
(EpaSpan { examples/Syntax.hs:24:5-6 })
(NormalSyntax))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:3 })
(AnnListItem
[])
(EpaComments
[]))
(VarPat
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:3 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:8-9 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:24:8-9 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: xs}))))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:3-21 })
(AnnListItem
[])
(EpaComments
[]))
(LetStmt
(EpTok
(EpaSpan { examples/Syntax.hs:25:3-5 }))
(HsValBinds
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnList
(Just
(EpaSpan { examples/Syntax.hs:25:7-21 }))
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
(ValBinds
(NoAnnSortKey)
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnListItem
[])
(EpaComments
[]))
(FunBind
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: doubled}))
(MG
(FromSource)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnList
(Nothing)
(ListNone)
[]
(NoEpTok)
[])
(EpaComments
[]))
[(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-21 })
(AnnListItem
[])
(EpaComments
[]))
(Match
(NoExtField)
(FunRhs
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:7-13 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: doubled}))
(Prefix)
(NoSrcStrict)
(AnnFunRhs
(NoEpTok)
[]
[]))
(L
(EpaSpan { <no location info> })
[])
(GRHSs
(EpaComments
[])
(:|
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:15-21 })
(NoEpAnns)
(EpaComments
[]))
(GRHS
(EpAnn
(EpaSpan { examples/Syntax.hs:25:15-21 })
(GrhsAnn
(Nothing)
(Left
(EpTok
(EpaSpan { examples/Syntax.hs:25:15 }))))
(EpaComments
[]))
[]
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:17-21 })
(AnnListItem
[])
(EpaComments
[]))
(OpApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:17 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:17 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: x}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:19 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:19 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: *}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:25:21 })
(AnnListItem
[])
(EpaComments
[]))
(HsOverLit
(NoExtField)
(OverLit
(NoExtField)
(HsIntegral
(IL
(SourceText 2)
(False)
(2))))))))))
[])
(EmptyLocalBinds
(NoExtField)))))]))))]
[]))))
,(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-14 })
(AnnListItem
[])
(EpaComments
[]))
(BodyStmt
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsApp
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-6 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:3-6 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: pure}))))
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:8-14 })
(AnnListItem
[])
(EpaComments
[]))
(HsVar
(NoExtField)
(L
(EpAnn
(EpaSpan { examples/Syntax.hs:26:8-14 })
(NameAnnTrailing
[])
(EpaComments
[]))
(Unqual
{OccName: doubled}))))))
(NoExtField)
(NoExtField)))])))))
[])
(EmptyLocalBinds
(NoExtField)))))])))))]))The same tree, pretty-printed back out as Haskell: note what layout became.
module Syntax where
infixl 6 |+|
(|+|) :: Int -> Int -> Int
x |+| y = x + y * 2
total :: [Int] -> Int
total xs = sum (map (|+| 1) xs)
greet :: Maybe String -> String
greet name
= case name of
Just n -> "hello, " ++ n
Nothing -> "hello"
collect :: [Int] -> [Int]
collect xs
= do x <- xs
let doubled = x * 2
pure doubledmodule Syntax where
infixl 6 |+|
(|+|) :: Int -> Int -> Int
x |+| y = x + y * 2
total :: [Int] -> Int
total xs = sum (map (|+| 1) xs)
greet :: Maybe String -> String
greet name
= case name of
Just n -> "hello, " ++ n
Nothing -> "hello"
collect :: [Int] -> [Int]
collect xs
= do x <- xs
let doubled = x * 2
pure doubledEvery name now resolved to the specific entity it refers to. The readable view suppresses the qualifiers; flip Full detail to see them.
infixl 6 |+|
(|+|) :: Int -> Int -> Int
x |+| y = x + y * 2
total :: [Int] -> Int
total xs = sum (map (|+| 1) xs)
greet :: Maybe String -> String
greet name
= case name of
Just n -> "hello, " ++ n
Nothing -> "hello"
collect :: [Int] -> [Int]
collect xs
= do x <- xs
let doubled = x * 2
pure doubledinfixl 6 Syntax.|+|
(Syntax.|+|) :: Int -> Int -> Int
x Syntax.|+| y = x + y * 2
Syntax.total :: [Int] -> Int
Syntax.total xs = sum (map (Syntax.|+| 1) xs)
Syntax.greet :: Maybe String -> String
Syntax.greet name
= case name of
Just n -> "hello, " ++ n
Nothing -> "hello"
Syntax.collect :: [Int] -> [Int]
Syntax.collect xs
= do x <- xs
let doubled = x * 2
pure doubledThe elaborated program: AbsBinds wrappers, dictionary arguments at call sites, and Evidence lines naming the instance each solved constraint resolved to.
$trModule = Module (TrNameS "main"#) (TrNameS "Syntax"#)
AbsBinds [] []
{Exports: [collect <= collect
wrap: <>]
Exported types: collect :: [Int] -> [Int]
Binds: collect xs
= do x <- xs
let doubled = x * 2
pure doubled
Evidence: [EvBinds{}]}
AbsBinds [] []
{Exports: [greet <= greet
wrap: <>]
Exported types: greet :: Maybe String -> String
Binds: greet name
= case name of
Just{EvBinds{}} n -> "hello, " ++ n
Nothing{EvBinds{}} -> "hello"
Evidence: [EvBinds{}]}
AbsBinds [] []
{Exports: [|+| <= |+|
wrap: <>]
Exported types: (|+|) :: Int -> Int -> Int
Binds: x |+| y = x + y * 2
Evidence: [EvBinds{}]}
AbsBinds [] []
{Exports: [total <= total
wrap: <>]
Exported types: total :: [Int] -> Int
Binds: total xs
= sum @[] $dFoldable @Int $dNum (map @Int @Int (|+| 1) xs)
Evidence: [EvBinds{}]}Syntax.$trModule
= GHC.Internal.Types.Module
(GHC.Internal.Types.TrNameS "main"#)
(GHC.Internal.Types.TrNameS "Syntax"#)
AbsBinds [] []
{Exports: [collect <= collect
wrap: <>]
Exported types: collect :: [Int] -> [Int]
[LclId]
Binds: collect xs
= do x <- xs
let doubled = x * 2
pure doubled
Evidence: [EvBinds{}]}
AbsBinds [] []
{Exports: [greet <= greet
wrap: <>]
Exported types: greet :: Maybe String -> String
[LclId]
Binds: greet name
= case name of
Just{EvBinds{}} n -> "hello, " ++ n
Nothing{EvBinds{}} -> "hello"
Evidence: [EvBinds{}]}
AbsBinds [] []
{Exports: [|+| <= |+|
wrap: <>]
Exported types: (|+|) :: Int -> Int -> Int
[LclId]
Binds: x |+| y = x + y * 2
Evidence: [EvBinds{}]}
AbsBinds [] []
{Exports: [total <= total
wrap: <>]
Exported types: total :: [Int] -> Int
[LclId]
Binds: total xs
= sum @[] $dFoldable @Int $dNum (map @Int @Int (|+| 1) xs)
Evidence: [EvBinds{}]}Every top-level type as the typechecker finally inferred it, hidden foralls included.
TYPE SIGNATURES collect :: [Int] -> [Int] greet :: Maybe String -> String total :: [Int] -> Int (|+|) :: Int -> Int -> Int Dependent modules: [] Dependent packages: [(normal, base-4.22.0.0)]
TYPE SIGNATURES collect :: [Int] -> [Int] greet :: Maybe String -> String total :: [Int] -> Int (|+|) :: Int -> Int -> Int Dependent modules: [] Dependent packages: [(normal, base-4.22.0.0)]
All of Haskell reduced to Core, before any optimisation.
Result size of Desugar (after optimization)
= {terms: 56, types: 41, coercions: 0, joins: 0/1}
-- RHS size: {terms: 11, types: 6, coercions: 0, joins: 0/0}
greet :: Maybe String -> String
greet
= \ (name :: Maybe String) ->
case name of {
Nothing -> unpackCString# "hello"#;
Just n -> ++ (unpackCString# "hello, "#) n
}
-- RHS size: {terms: 5, types: 0, coercions: 0, joins: 0/0}
$trModule :: Module
$trModule = Module (TrNameS "main"#) (TrNameS "Syntax"#)
-- RHS size: {terms: 10, types: 4, coercions: 0, joins: 0/0}
(|+|) :: Int -> Int -> Int
(|+|)
= \ (x :: Int) (y :: Int) -> + $fNumInt x (* $fNumInt y (I# 2#))
-- RHS size: {terms: 13, types: 8, coercions: 0, joins: 0/1}
total :: [Int] -> Int
total
= \ (xs :: [Int]) ->
sum
$fFoldableList
$fNumInt
(map
(let {
v :: Int
v = I# 1# } in
\ (v :: Int) -> |+| v v)
xs)
-- RHS size: {terms: 12, types: 9, coercions: 0, joins: 0/0}
collect :: [Int] -> [Int]
collect
= \ (xs :: [Int]) ->
>>=
$fMonadList
xs
(\ (x :: Int) -> pure $fApplicativeList (* $fNumInt x (I# 2#)))Result size of Desugar (after optimization)
= {terms: 56, types: 41, coercions: 0, joins: 0/1}
-- RHS size: {terms: 11, types: 6, coercions: 0, joins: 0/0}
greet :: Maybe String -> String
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [80] 150 0}]
greet
= \ (name :: Maybe String) ->
case name of {
Nothing -> GHC.Internal.CString.unpackCString# "hello"#;
Just n ->
++ @Char (GHC.Internal.CString.unpackCString# "hello, "#) n
}
-- RHS size: {terms: 5, types: 0, coercions: 0, joins: 0/0}
Syntax.$trModule :: GHC.Internal.Types.Module
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 80 10}]
Syntax.$trModule
= GHC.Internal.Types.Module
(GHC.Internal.Types.TrNameS "main"#)
(GHC.Internal.Types.TrNameS "Syntax"#)
-- RHS size: {terms: 10, types: 4, coercions: 0, joins: 0/0}
(|+|) :: Int -> Int -> Int
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [0 0] 90 0}]
(|+|)
= \ (x :: Int) (y :: Int) ->
+ @Int
GHC.Internal.Num.$fNumInt
x
(* @Int GHC.Internal.Num.$fNumInt y (GHC.Internal.Types.I# 2#))
-- RHS size: {terms: 13, types: 8, coercions: 0, joins: 0/1}
total :: [Int] -> Int
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [0] 130 0}]
total
= \ (xs :: [Int]) ->
sum
@[]
GHC.Internal.Data.Foldable.$fFoldableList
@Int
GHC.Internal.Num.$fNumInt
(map
@Int
@Int
(let {
v :: Int
[LclId,
Unf=Unf{Src=<vanilla>, TopLvl=False,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 10 10}]
v = GHC.Internal.Types.I# 1# } in
\ (v :: Int) -> |+| v v)
xs)
-- RHS size: {terms: 12, types: 9, coercions: 0, joins: 0/0}
collect :: [Int] -> [Int]
[LclIdX,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [0] 130 0}]
collect
= \ (xs :: [Int]) ->
>>=
@[]
GHC.Internal.Base.$fMonadList
@Int
@Int
xs
(\ (x :: Int) ->
pure
@[]
GHC.Internal.Base.$fApplicativeList
@Int
(* @Int GHC.Internal.Num.$fNumInt x (GHC.Internal.Types.I# 2#)))The same program after the simplifier has run.
Result size of Tidy Core
= {terms: 90, types: 61, coercions: 0, joins: 0/0}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
greet3 :: Addr#
greet3 = "hello"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
greet2 :: [Char]
greet2 = unpackCString# greet3
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
greet1 :: Addr#
greet1 = "hello, "#
-- RHS size: {terms: 9, types: 5, coercions: 0, joins: 0/0}
greet :: Maybe String -> String
greet
= \ (name :: Maybe String) ->
case name of {
Nothing -> greet2;
Just n -> unpackAppendCString# greet1 n
}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
$trModule4 :: Addr#
$trModule4 = "main"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
$trModule3 :: TrName
$trModule3 = TrNameS $trModule4
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
$trModule2 :: Addr#
$trModule2 = "Syntax"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
$trModule1 :: TrName
$trModule1 = TrNameS $trModule2
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
$trModule :: Module
$trModule = Module $trModule3 $trModule1
-- RHS size: {terms: 14, types: 6, coercions: 0, joins: 0/0}
(|+|) :: Int -> Int -> Int
(|+|)
= \ (x :: Int) (y :: Int) ->
case x of { I# x1 -> case y of { I# x2 -> I# (+# x1 (*# x2 2#)) } }
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
total1 :: Int
total1 = I# 0#
Rec {
-- RHS size: {terms: 18, types: 10, coercions: 0, joins: 0/0}
$wgo1 :: [Int] -> Int# -> Int
$wgo1
= \ (ds :: [Int]) (ww :: Int#) ->
case ds of {
[] -> I# ww;
: y ys -> case y of { I# x -> $wgo1 ys (+# 2# (+# ww x)) }
}
end Rec }
-- RHS size: {terms: 4, types: 2, coercions: 0, joins: 0/0}
total :: [Int] -> Int
total = \ (xs :: [Int]) -> $wgo1 xs 0#
Rec {
-- RHS size: {terms: 16, types: 11, coercions: 0, joins: 0/0}
collect :: [Int] -> [Int]
collect
= \ (ds :: [Int]) ->
case ds of {
[] -> [];
: y ys -> : (case y of { I# x -> I# (*# x 2#) }) (collect ys)
}
end Rec }Result size of Tidy Core
= {terms: 90, types: 61, coercions: 0, joins: 0/0}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
Syntax.greet3 :: GHC.Internal.Prim.Addr#
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 30 0}]
Syntax.greet3 = "hello"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
Syntax.greet2 :: [Char]
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=False, ConLike=True, WorkFree=False, Expandable=True,
Guidance=IF_ARGS [] 20 0}]
Syntax.greet2 = GHC.Internal.CString.unpackCString# Syntax.greet3
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
Syntax.greet1 :: GHC.Internal.Prim.Addr#
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 30 0}]
Syntax.greet1 = "hello, "#
-- RHS size: {terms: 9, types: 5, coercions: 0, joins: 0/0}
greet :: Maybe String -> String
[GblId,
Arity=1,
Str=<1L>,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [30] 50 0}]
greet
= \ (name :: Maybe String) ->
case name of {
Nothing -> Syntax.greet2;
Just n -> GHC.Internal.CString.unpackAppendCString# Syntax.greet1 n
}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
Syntax.$trModule4 :: GHC.Internal.Prim.Addr#
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 20 0}]
Syntax.$trModule4 = "main"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
Syntax.$trModule3 :: GHC.Internal.Types.TrName
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 10 10}]
Syntax.$trModule3 = GHC.Internal.Types.TrNameS Syntax.$trModule4
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
Syntax.$trModule2 :: GHC.Internal.Prim.Addr#
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 30 0}]
Syntax.$trModule2 = "Syntax"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
Syntax.$trModule1 :: GHC.Internal.Types.TrName
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 10 10}]
Syntax.$trModule1 = GHC.Internal.Types.TrNameS Syntax.$trModule2
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
Syntax.$trModule :: GHC.Internal.Types.Module
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 10 10}]
Syntax.$trModule
= GHC.Internal.Types.Module Syntax.$trModule3 Syntax.$trModule1
-- RHS size: {terms: 14, types: 6, coercions: 0, joins: 0/0}
(|+|) :: Int -> Int -> Int
[GblId,
Arity=2,
Str=<1!P(L)><1!P(L)>,
Cpr=1,
Unf=Unf{Src=StableSystem, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
Tmpl= \ (x [Occ=Once1!] :: Int) (y [Occ=Once1!] :: Int) ->
case x of { GHC.Internal.Types.I# x1 [Occ=Once1] ->
case y of { GHC.Internal.Types.I# x2 [Occ=Once1] ->
GHC.Internal.Types.I#
(GHC.Internal.Prim.+# x1 (GHC.Internal.Prim.*# x2 2#))
}
}}]
(|+|)
= \ (x :: Int) (y :: Int) ->
case x of { GHC.Internal.Types.I# x1 ->
case y of { GHC.Internal.Types.I# x2 ->
GHC.Internal.Types.I#
(GHC.Internal.Prim.+# x1 (GHC.Internal.Prim.*# x2 2#))
}
}
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
Syntax.total1 :: Int
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [] 10 10}]
Syntax.total1 = GHC.Internal.Types.I# 0#
Rec {
-- RHS size: {terms: 18, types: 10, coercions: 0, joins: 0/0}
$wgo1 :: [Int] -> GHC.Internal.Prim.Int# -> Int
[GblId[StrictWorker([!])], Arity=2, Str=<1L><L>, Unf=OtherCon []]
$wgo1
= \ (ds :: [Int]) (ww :: GHC.Internal.Prim.Int#) ->
case ds of {
[] -> GHC.Internal.Types.I# ww;
: y ys ->
case y of { GHC.Internal.Types.I# x ->
$wgo1 ys (GHC.Internal.Prim.+# 2# (GHC.Internal.Prim.+# ww x))
}
}
end Rec }
-- RHS size: {terms: 4, types: 2, coercions: 0, joins: 0/0}
total :: [Int] -> Int
[GblId,
Arity=1,
Str=<1L>,
Cpr=1,
Unf=Unf{Src=StableSystem, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False)
Tmpl= \ (xs [Occ=Once1] :: [Int]) ->
joinrec {
go1 [InlPrag=[2], Occ=T[2], Dmd=LC(S,C(1,!P(L)))]
:: [Int] -> Int -> Int
[LclId[JoinId(2)(Just [!, !])],
Arity=2,
Str=<SL><S!P(L)>,
Unf=Unf{Src=StableSystem, TopLvl=False,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
Tmpl= \ (ds [Occ=Once1] :: [Int])
(eta [Occ=Once1!, OS=OneShot] :: Int) ->
case eta of { GHC.Internal.Types.I# ww [Occ=Once1] ->
jump $wgo2 ds ww
}}]
go1 (ds [Occ=Once1] :: [Int]) (eta [Occ=Once1!, OS=OneShot] :: Int)
= case eta of { GHC.Internal.Types.I# ww [Occ=Once1] ->
jump $wgo2 ds ww
};
$wgo2 [InlPrag=[2], Occ=LoopBreakerT[2]]
:: [Int] -> GHC.Internal.Prim.Int# -> Int
[LclId[JoinId(2)(Just [!])], Arity=2, Str=<SL><L>, Unf=OtherCon []]
$wgo2 (ds [Occ=Once1!] :: [Int])
(ww [Occ=Once2] :: GHC.Internal.Prim.Int#)
= case ds of {
[] -> GHC.Internal.Types.I# ww;
: y [Occ=Once1!] ys [Occ=Once1] ->
case y of { GHC.Internal.Types.I# x [Occ=Once1] ->
jump go1
ys
(GHC.Internal.Types.I#
(GHC.Internal.Prim.+# 2# (GHC.Internal.Prim.+# ww x)))
}
}; } in
jump go1 xs Syntax.total1}]
total = \ (xs :: [Int]) -> $wgo1 xs 0#
Rec {
-- RHS size: {terms: 16, types: 11, coercions: 0, joins: 0/0}
collect [Occ=LoopBreaker] :: [Int] -> [Int]
[GblId, Arity=1, Str=<1L>, Unf=OtherCon []]
collect
= \ (ds :: [Int]) ->
case ds of {
[] -> GHC.Internal.Types.[] @Int;
: y ys ->
GHC.Internal.Types.:
@Int
(case y of { GHC.Internal.Types.I# x ->
GHC.Internal.Types.I# (GHC.Internal.Prim.*# x 2#)
})
(collect ys)
}
end Rec }Allocation and evaluation made explicit, ready for code generation.
$trModule2 :: Addr# = "Syntax"#;
$trModule4 :: Addr# = "main"#;
greet1 :: Addr# = "hello, "#;
greet3 :: Addr# = "hello"#;
greet2 :: [Char] = {} \u [] unpackCString# greet3;
greet :: Maybe String -> String =
{} \r [name]
case name of wild {
Nothing -> greet2;
Just n -> unpackAppendCString# greet1 n;
};
$trModule3 :: TrName = TrNameS! [$trModule4];
$trModule1 :: TrName = TrNameS! [$trModule2];
$trModule :: Module = Module! [$trModule3 $trModule1];
(|+|) :: Int -> Int -> Int =
{} \r [x y]
case x of wild {
I# x1 ->
case y of wild1 {
I# x2 ->
case *# [x2 2#] of |+|_sat {
__DEFAULT ->
case +# [x1 |+|_sat] of |+|_sat { __DEFAULT -> I# [|+|_sat]; };
};
};
};
total1 :: Int = I#! [0#];
Rec {
$wgo1 :: [Int] -> Int# -> Int =
{} \r [ds ww]
case ds<TagProper> of wild {
[] -> I# [ww];
: y ys ->
case y of wild1 {
I# x ->
case +# [ww x] of $wgo1_sat {
__DEFAULT ->
case +# [2# $wgo1_sat] of $wgo1_sat {
__DEFAULT -> case ys of ys { __DEFAULT -> $wgo1 ys $wgo1_sat; };
};
};
};
};
end Rec }
total :: [Int] -> Int =
{} \r [xs] case xs of xs { __DEFAULT -> $wgo1 xs 0#; };
Rec {
collect :: [Int] -> [Int] =
{} \r [ds]
case ds of wild {
[] -> [] [];
: y ys ->
let { collect_sat :: [Int] = {ys} \u [] collect ys; } in
let {
collect_sat :: Int =
{y} \u []
case y of wild1 {
I# x ->
case *# [x 2#] of collect_sat { __DEFAULT -> I# [collect_sat]; };
};
} in : [collect_sat collect_sat];
};
end Rec }Syntax.$trModule2 :: GHC.Internal.Prim.Addr#
[GblId, Unf=OtherCon []] =
"Syntax"#;
Syntax.$trModule4 :: GHC.Internal.Prim.Addr#
[GblId, Unf=OtherCon []] =
"main"#;
Syntax.greet1 :: GHC.Internal.Prim.Addr#
[GblId, Unf=OtherCon []] =
"hello, "#;
Syntax.greet3 :: GHC.Internal.Prim.Addr#
[GblId, Unf=OtherCon []] =
"hello"#;
Syntax.greet2 :: [GHC.Internal.Types.Char]
[GblId] =
{} \u [] GHC.Internal.CString.unpackCString# Syntax.greet3;
Syntax.greet
:: GHC.Internal.Maybe.Maybe GHC.Internal.Base.String
-> GHC.Internal.Base.String
[GblId, Arity=1, Str=<1L>, Unf=OtherCon []] =
{} \r [name]
case name of wild {
GHC.Internal.Maybe.Nothing -> Syntax.greet2;
GHC.Internal.Maybe.Just n [Occ=Once1] ->
GHC.Internal.CString.unpackAppendCString# Syntax.greet1 n;
};
Syntax.$trModule3 :: GHC.Internal.Types.TrName
[GblId, Unf=OtherCon []] =
GHC.Internal.Types.TrNameS! [Syntax.$trModule4];
Syntax.$trModule1 :: GHC.Internal.Types.TrName
[GblId, Unf=OtherCon []] =
GHC.Internal.Types.TrNameS! [Syntax.$trModule2];
Syntax.$trModule :: GHC.Internal.Types.Module
[GblId, Unf=OtherCon []] =
GHC.Internal.Types.Module! [Syntax.$trModule3 Syntax.$trModule1];
(Syntax.|+|)
:: GHC.Internal.Types.Int
-> GHC.Internal.Types.Int -> GHC.Internal.Types.Int
[GblId, Arity=2, Str=<1!P(L)><1!P(L)>, Cpr=1, Unf=OtherCon []] =
{} \r [x y]
case x of wild {
GHC.Internal.Types.I# x1 [Occ=Once1] ->
case y of wild1 {
GHC.Internal.Types.I# x2 [Occ=Once1] ->
case *# [x2 2#] of |+|_sat {
__DEFAULT ->
case +# [x1 |+|_sat] of |+|_sat {
__DEFAULT -> GHC.Internal.Types.I# [|+|_sat];
};
};
};
};
Syntax.total1 :: GHC.Internal.Types.Int
[GblId, Unf=OtherCon []] =
GHC.Internal.Types.I#! [0#];
Rec {
$wgo1
:: [GHC.Internal.Types.Int]
-> GHC.Internal.Prim.Int# -> GHC.Internal.Types.Int
[GblId[StrictWorker([!])], Arity=2, Str=<1L><L>, Unf=OtherCon []] =
{} \r [ds ww]
case ds<TagProper> of wild {
[] -> GHC.Internal.Types.I# [ww];
: y [Occ=Once1!] ys [Occ=Once1] ->
case y of wild1 {
GHC.Internal.Types.I# x [Occ=Once1] ->
case +# [ww x] of $wgo1_sat {
__DEFAULT ->
case +# [2# $wgo1_sat] of $wgo1_sat {
__DEFAULT -> case ys of ys { __DEFAULT -> $wgo1 ys $wgo1_sat; };
};
};
};
};
end Rec }
Syntax.total :: [GHC.Internal.Types.Int] -> GHC.Internal.Types.Int
[GblId, Arity=1, Str=<1L>, Cpr=1, Unf=OtherCon []] =
{} \r [xs] case xs of xs { __DEFAULT -> $wgo1 xs 0#; };
Rec {
Syntax.collect [Occ=LoopBreaker]
:: [GHC.Internal.Types.Int] -> [GHC.Internal.Types.Int]
[GblId, Arity=1, Str=<1L>, Unf=OtherCon []] =
{} \r [ds]
case ds of wild {
[] -> [] [];
: y [Occ=Once1!] ys [Occ=Once1] ->
let {
collect_sat [Occ=Once1] :: [GHC.Internal.Types.Int]
[LclId] =
{ys} \u [] Syntax.collect ys; } in
let {
collect_sat [Occ=Once1] :: GHC.Internal.Types.Int
[LclId] =
{y} \u []
case y of wild1 {
GHC.Internal.Types.I# x [Occ=Once1] ->
case *# [x 2#] of collect_sat {
__DEFAULT -> GHC.Internal.Types.I# [collect_sat];
};
};
} in : [collect_sat collect_sat];
};
end Rec }Two things are worth pausing on.
In Parsed, the layout you wrote has become explicit braces and semicolons:
that is the offside rule’s output, made visible. And in Parsed AST, notice
how much of the bulk is EpAnn and Anchor nodes recording exact source
positions: the annotations from the previous section, in the flesh.
Notice also what has not happened. x |+| y * 2 sits in the tree as a flat
OpApp chain with no grouping, even though |+| is declared infixl 6 right
there in the file. Fixity resolution needs to know the fixity of every operator
in scope, including imported ones, and that information does not exist yet. It
arrives with the renamer, in the next chapter.
What the parser hands on
The output is HsModule GhcPs. That GhcPs is a phase index: the same AST types
are reused by the renamer as GhcRn and the typechecker as GhcTc, with
different field types at each stage. The technique is called Trees That Grow,
and it is why GHC/Hs/Expr.hs is full of type families rather than concrete
fields.
At GhcPs, every identifier is a RdrName: a name exactly as written,
qualified or not, with no idea what it refers to. Turning those into Names that
point at actual entities is the renamer’s job.
Reading the source yourself
If you want to work on the front end, a reasonable order is:
GHC/Parser/Lexer.x, bottom half first. The Haskell preamble (P,PState,new_layout_context,maybe_layout) is more approachable than the Alex rules above it, and explains what those rules are doing.GHC/Parser.y, starting with its Notes rather than its productions. The preamble Notes explain the conventions the 4,700 lines below them follow.GHC/Parser/PostProcess.hslast, onceDisambECPhas a reason to exist.
The parser is also the easiest phase in which to make a first contribution: its
behaviour is observable from the outside with -ddump-parsed-ast, its tests are
plain source files, and a change here cannot silently miscompile anything.
Either it parses or it does not.