Chapter 7. GHC Language Features

Table of Contents
7.1. Language options
7.2. Unboxed types and primitive operations
7.3. Primitive state-transformer monad
7.4. Primitive arrays, mutable and otherwise
7.5. Data types with no constructors
7.6. Pattern guards
7.7. Parallel List Comprehensions
7.8. Multi-parameter type classes
7.9. Implicit parameters
7.10. Functional dependencies
7.11. Explicit universal quantification
7.12. Existentially quantified data constructors
7.13. Assertions
7.14. Scoped Type Variables
7.15. Pragmas
7.16. Rewrite rules
7.17. Generic classes
7.18. Concurrent and Parallel Haskell
7.19. Haskell 98 vs. Glasgow Haskell: language non-compliance

As with all known Haskell systems, GHC implements some extensions to the language. To use them, you'll need to give a -fglasgow-exts option.

Virtually all of the Glasgow extensions serve to give you access to the underlying facilities with which we implement Haskell. Thus, you can get at the Raw Iron, if you are willing to write some non-standard code at a more primitive level. You need not be “stuck” on performance because of the implementation costs of Haskell's “high-level” features—you can always code “under” them. In an extreme case, you can write all your time-critical code in C, and then just glue it together with Haskell!

Executive summary of our extensions:

Unboxed types and primitive operations:

You can get right down to the raw machine types and operations; included in this are “primitive arrays” (direct access to Big Wads of Bytes). Please see Section 7.2.1 and following.

Type system extensions:

GHC supports a large number of extensions to Haskell's type system. Specifically:

Multi-parameter type classes:

Section 7.8

Functional dependencies:

Section 7.10

Implicit parameters:

Section 7.9

Local universal quantification:

Section 7.11

Extistentially quantification in data types:

Section 7.12

Scoped type variables:

Scoped type variables enable the programmer to supply type signatures for some nested declarations, where this would not be legal in Haskell 98. Details in Section 7.14.

Pattern guards

Instead of being a boolean expression, a guard is a list of qualifiers, exactly as in a list comprehension. See Section 7.6.

Data types with no constructors

See Section 7.5.

Parallel list comprehensions

An extension to the list comprehension syntax to support zipWith-like functionality. See Section 7.7.

Foreign calling:

Just what it sounds like. We provide lots of rope that you can dangle around your neck. Please see Chapter 8.

Pragmas

Pragmas are special instructions to the compiler placed in the source file. The pragmas GHC supports are described in Section 7.15.

Rewrite rules:

The programmer can specify rewrite rules as part of the source program (in a pragma). GHC applies these rewrite rules wherever it can. Details in Section 7.16.

Generic classes:

(Note: support for generic classes is currently broken in GHC 5.02).

Generic class declarations allow you to define a class whose methods say how to work over an arbitrary data type. Then it's really easy to make any new type into an instance of the class. This generalises the rather ad-hoc "deriving" feature of Haskell 98. Details in Section 7.17.

Before you get too carried away working at the lowest level (e.g., sloshing MutableByteArray#s around your program), you may wish to check if there are libraries that provide a “Haskellised veneer” over the features you want. See Haskell Libraries.

7.1. Language options

These flags control what variation of the language are permitted. Leaving out all of them gives you standard Haskell 98.

-fglasgow-exts:

This simultaneously enables all of the extensions to Haskell 98 described in Chapter 7, except where otherwise noted.

-fno-monomorphism-restriction:

Switch off the Haskell 98 monomorphism restriction. Independent of the -fglasgow-exts flag.

-fallow-overlapping-instances, -fallow-undecidable-instances, -fcontext-stack

See Section 7.8.3. Only relevant if you also use -fglasgow-exts.

-finline-phase

See Section 7.16. Only relevant if you also use -fglasgow-exts.

-fgenerics

See Section 7.17. Independent of -fglasgow-exts.

-fno-implicit-prelude

GHC normally imports Prelude.hi files for you. If you'd rather it didn't, then give it a -fno-implicit-prelude option. The idea is that you can then import a Prelude of your own. (But don't call it Prelude; the Haskell module namespace is flat, and you must not conflict with any Prelude module.)

Even though you have not imported the Prelude, all the built-in syntax still refers to the built-in Haskell Prelude types and values, as specified by the Haskell Report. For example, the type [Int] still means Prelude.[] Int; tuples continue to refer to the standard Prelude tuples; the translation for list comprehensions continues to use Prelude.map etc.

With one group of exceptions! You may want to define your own numeric class hierarchy. It completely defeats that purpose if the literal "1" means "Prelude.fromInteger 1", which is what the Haskell Report specifies. So the -fno-implicit-prelude flag causes the following pieces of built-in syntax to refer to whatever is in scope, not the Prelude versions:

  • Integer and fractional literals mean "fromInteger 1" and "fromRational 3.2", not the Prelude-qualified versions; both in expressions and in patterns.

  • Negation (e.g. "- (f x)") means "negate (f x)" (not Prelude.negate).

  • In an n+k pattern, the standard Prelude Ord class is still used for comparison, but the necessary subtraction uses whatever "(-)" is in scope (not "Prelude.(-)").

Note: Negative literals, such as -3, are specified by (a careful reading of) the Haskell Report as meaning Prelude.negate (Prelude.fromInteger 3). However, GHC deviates from this slightly, and treats them as meaning fromInteger (-3). One particular effect of this slightly-non-standard reading is that there is no difficulty with the literal -2147483648 at type Int; it means fromInteger (-2147483648). The strict interpretation would be negate (fromInteger 2147483648), and the call to fromInteger would overflow (at type Int, remember).