This is the data type that represents GHCs core intermediate language.
Currently GHC uses System FC
https://www.microsoft.com/en-us/research/publication/system-f-with-type-equality-coercions/
for this purpose, which is closely related to the simpler and better
known System F
http://en.wikipedia.org/wiki/System_F.
We get from Haskell source to this Core language in a number of
stages:
- The source code is parsed into an abstract syntax tree, which is
represented by the data type HsExpr with the names being
RdrNames
- This syntax tree is renamed, which attaches a Unique
to every RdrName (yielding a Name) to disambiguate
identifiers which are lexically identical. For example, this
program:
f x = let f x = x + 1
in f (x - 2)
Would be renamed by having
Uniques attached so it looked
something like this:
f_1 x_2 = let f_3 x_4 = x_4 + 1
in f_3 (x_2 - 2)
But see Note [Shadowing in Core] below.
- The resulting syntax tree undergoes type checking (which also
deals with instantiating type class arguments) to yield a
HsExpr type that has Id as it's names.
- Finally the syntax tree is desugared from the expressive
HsExpr type into this Expr type, which has far fewer
constructors and hence is easier to perform optimization, analysis and
code generation on.
The type parameter
b is for the type of binders in the
expression tree.
The language consists of the following elements:
- Variables See Note [Variable occurrences in Core]
- Primitive literals
- Applications: note that the argument may be a Type. See
Note [Representation polymorphism invariants]
- Lambda abstraction See Note [Representation polymorphism
invariants]
- Recursive and non recursive lets. Operationally this
corresponds to allocating a thunk for the things bound and then
executing the sub-expression.
See Note [Core letrec invariant] See Note [Core let-can-float
invariant] See Note [Representation polymorphism invariants] See Note
[Core type and coercion invariant]
- Case expression. Operationally this corresponds to evaluating the
scrutinee (expression examined) to weak head normal form and then
examining at most one level of resulting constructor (i.e. you cannot
do nested pattern matching directly with this).
The binder gets bound to the value of the scrutinee, and the
Type must be that of all the case alternatives
IMPORTANT: see Note [Case expression invariants]
- Cast an expression to a particular type. This is used to implement
newtypes (a newtype constructor or destructor just
becomes a Cast in Core) and GADTs.
- Ticks. These are used to represent all the source annotation we
support: profiling SCCs, HPC ticks, and GHCi breakpoints.
- A type: this should only show up at the top level of an Arg
- A coercion