Introduction to GHC language extensions

One of the most intimidating aspects of being new to Haskell are the overwhelming number of language extensions GHC Haskell has to offer. Some are well documented, others are sparsely documented; some seem to appear in so much “real world” Haskell code; some are spoken of in hushed tones as being unsafe and unwise while others are … maybe safe? It can be difficult terrain to navigate.

The first thing to understand is that most programs can be written in vanilla Haskell2010 or even Haskell98 with no extensions enabled. The extensions do not change the languages or its semantics. They are compiler extensions and change the way the compiler does its job, the way it reads the code. Hence, if you are using a compiler other than GHC (or are using a very old version of GHC), you may not have access to any of these extensions or only to some subset.

This course covers the ones we think are most likely to be useful and helpful to the Haskell beginner or early intermediate as well as a few having to do with issues that crop up whether you’re ready for them or not. Each has a link to a longer article about it, describing it in more detail.

What is a language extension?

Language extensions can be enabled using a pragma called LANGUAGE. A pragmaApparently this use of the term ‘pragma’ originates with ALGOL 68, although it was pragmat then, and is derived from the word pragmatic. is an instruction to the compiler about how to process the input code. They can, for instance, be used to specify certain optimization rules so the compiler handles the code a bit differently from normal.

Pragmas do not generally affect the semantics of your program, but can, for example, allow variations in syntax or alter the way the program is evaluated. The word pragma derives from the same sense of pragmatic that linguists use to talk about the way context can change the way utterances are understood, without affecting the basic semantics of the utterance.

GHC supports several pragmas. They are all written inside special comment syntax ({-# ... #-}) with the name of the pragma in all caps followed by any information specific to that type of pragma, such as the name of a language extension or compiler flag:

{-# LANGUAGE <NameOfExtension> #-}
{-# OPTIONS_GHC <compiler_flag> #-}
{-# INLINE <function_name> #-}
{- This is a regular block comment, not a pragma -}

The LANGUAGE pragma is used to enable extensions to the Haskell language. Sometimes the changed syntax they enable is merely convenient, but many of them allow you to write Haskell very differently from the basic language as specified in the Haskell Report.

LANGUAGE is a file-header pragmaSome pragmas, such as INLINE, are not written at the top of a file and their scope is limited. See the documentation for more information., so language extensions are listed at the very top of the file, above the module name, and the entire file will be compiled in that context – although it is ok to turn on a language extension and then never use the syntax it enables within that file. This isn’t really recommended and can have (usually small) effects on compile time but you won’t break anything by turning some extensions on and then not using them (or deleting the code that did need them but forgetting to delete the pragma).

Every language extensionA list of all the language extensions your version of GHC supports can be obtained by invoking ghc --supported-extensions. can also be turned into a command-line flag by prefixing it with -X; for example -XForeignFunctionInterface. So, for example, you can turn that on when you invoke GHC on the command line to compile your program. You can also use that to turn them on in GHCi, using GHCi’s :set command, e.g., :set -XTypeApplications. The :set command can also go in your GHCi configuration, to enable an extension by default whenever you start GHCi. You can also turn language extensions onIf you are using hpack, you can turn on language extensions in your package.yaml file. for an entire project using the default-extensions field in your .cabal file.

Implications

Some language extensions build on others: for example, ExplicitForAll introduces the forall keyword, and ScopedTypeVariables expands upon the significance of forall. Since scoped type variables would not be useful without forall, GHC enables ExplicitForAll automatically whenever you turn on ScopedTypeVariables. In this course, we depict this relationship as follows:

ScopedTypeVariables ExplicitForAll

We read this as “ScopedTypeVariables implies ExplicitForAll”.

Join Type Classes for courses and projects to get you started and make you an expert in FP with Haskell.