The first internal representation in GHC is Core, the second one is STG, and the third one Cmm. Both Core and STG are very functional, while Cmm is an imperative language which resembles C a lot. In this section we will learn to read GHC Core and to spot possible performance problems that might otherwise be hard to spot.
Core is the intermediate language within GHC. Nearly all optimizations GHC does are only program transformations from Core to Core. Reading Core is pretty straightforward for anyone who has read Haskell. For the most part, Core is just let bindings, pattern matches, and function applications. The challenge is in naming conventions, because Core can be quite a noisy code. Following this is a (recursive) function definition in Core (with added line numbering):
1 Rec { 2 foo_rjH 3 foo_rjH = 4 \ ds_d1ya -> 5 case ds_d1ya of wild_X5 { I# ds1_d1yb -> 6 case ds1_d1yb of _ { 7 __DEFAULT -> 8 ...