<indexterm><primary>language, GHC</primary></indexterm>
<indexterm><primary>extensions, GHC</primary></indexterm>
As with all known Haskell systems, GHC implements some extensions to
-the language. To use them, you'll need to give a <option>-fglasgow-exts</option>
-<indexterm><primary>-fglasgow-exts option</primary></indexterm> option.
+the language. They are all enabled by options; by default GHC
+understands only plain Haskell 98.
</para>
<para>
-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!
+Some 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-portable
+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!
</para>
<para>
sloshing <literal>MutableByteArray#</literal>s around your
program), you may wish to check if there are libraries that provide a
“Haskellised veneer” over the features you want. The
-separate libraries documentation describes all the libraries that come
-with GHC.
+separate <ulink url="../libraries/index.html">libraries
+documentation</ulink> describes all the libraries that come with GHC.
</para>
<!-- LANGUAGE OPTIONS -->
<indexterm><primary>extensions</primary><secondary>options controlling</secondary>
</indexterm>
- <para> These flags control what variation of the language are
+ <para>These flags control what variation of the language are
permitted. Leaving out all of them gives you standard Haskell
98.</para>
+ <para>NB. turning on an option that enables special syntax
+ <emphasis>might</emphasis> cause working Haskell 98 code to fail
+ to compile, perhaps because it uses a variable name which has
+ become a reserved word. So, together with each option below, we
+ list the special syntax which is enabled by this option. We use
+ notation and nonterminal names from the Haskell 98 lexical syntax
+ (see the Haskell 98 Report). There are two classes of special
+ syntax:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>New reserved words and symbols: character sequences
+ which are no longer available for use as identifiers in the
+ program.</para>
+ </listitem>
+ <listitem>
+ <para>Other special syntax: sequences of characters that have
+ a different meaning when this particular option is turned
+ on.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>We are only listing syntax changes here that might affect
+ existing working programs (i.e. "stolen" syntax). Many of these
+ extensions will also enable new context-free syntax, but in all
+ cases programs written to use the new syntax would not be
+ compilable without the option enabled.</para>
+
<variablelist>
<varlistentry>
Haskell 98 described in <xref
linkend="ghc-language-features">, except where otherwise
noted. </para>
+
+ <para>New reserved words: <literal>forall</literal> (only in
+ types), <literal>mdo</literal>.</para>
+
+ <para>Other syntax stolen:
+ <replaceable>varid</replaceable>{<literal>#</literal>},
+ <replaceable>char</replaceable><literal>#</literal>,
+ <replaceable>string</replaceable><literal>#</literal>,
+ <replaceable>integer</replaceable><literal>#</literal>,
+ <replaceable>float</replaceable><literal>#</literal>,
+ <replaceable>float</replaceable><literal>##</literal>,
+ <literal>(#</literal>, <literal>#)</literal>,
+ <literal>|)</literal>, <literal>{|</literal>.</para>
</listitem>
</varlistentry>
Haskell 98 Foreign Function Interface Addendum plus deprecated
syntax of previous versions of the FFI for backwards
compatibility.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>-fwith</option>:</term>
- <indexterm><primary><option>-fwith</option></primary></indexterm>
- <listitem>
- <para>This option enables the deprecated <literal>with</literal>
- keyword for implicit parameters; it is merely provided for backwards
- compatibility.
- It is independent of the <option>-fglasgow-exts</option>
- flag. </para>
+ <para>New reserved words: <literal>foreign</literal>.</para>
</listitem>
</varlistentry>
<listitem>
<para>See <xref LinkEnd="arrow-notation">. Independent of
<option>-fglasgow-exts</option>.</para>
+
+ <para>New reserved words/symbols: <literal>rec</literal>,
+ <literal>proc</literal>, <literal>-<</literal>,
+ <literal>>-</literal>, <literal>-<<</literal>,
+ <literal>>>-</literal>.</para>
+
+ <para>Other syntax stolen: <literal>(|</literal>,
+ <literal>|)</literal>.</para>
</listitem>
</varlistentry>
<para>Enables Template Haskell (see <xref
linkend="template-haskell">). Currently also implied by
<option>-fglasgow-exts</option>.</para>
+
+ <para>Syntax stolen: <literal>[|</literal>,
+ <literal>[e|</literal>, <literal>[p|</literal>,
+ <literal>[d|</literal>, <literal>[t|</literal>,
+ <literal>$(</literal>,
+ <literal>$<replaceable>varid</replaceable></literal>.</para>
</listitem>
</varlistentry>
<para>Enables implicit parameters (see <xref
linkend="implicit-parameters">). Currently also implied by
<option>-fglasgow-exts</option>.</para>
+
+ <para>Syntax stolen:
+ <literal>?<replaceable>varid</replaceable></literal>,
+ <literal>%<replaceable>varid</replaceable></literal>.</para>
</listitem>
</varlistentry>
</programlisting>
-Reason: a value of type <literal>T</literal> must be represented as a pair
-of a dictionary for <literal>Ord t</literal> and a value of type <literal>t</literal>.
-That contradicts the idea that <literal>newtype</literal> should have no
-concrete representation. You can get just the same efficiency and effect
-by using <literal>data</literal> instead of <literal>newtype</literal>. If there is no
-overloading involved, then there is more of a case for allowing
-an existentially-quantified <literal>newtype</literal>, because the <literal>data</literal>
-because the <literal>data</literal> version does carry an implementation cost,
-but single-field existentially quantified constructors aren't much
-use. So the simple restriction (no existential stuff on <literal>newtype</literal>)
-stands, unless there are convincing reasons to change it.
+Reason: a value of type <literal>T</literal> must be represented as a
+pair of a dictionary for <literal>Ord t</literal> and a value of type
+<literal>t</literal>. That contradicts the idea that
+<literal>newtype</literal> should have no concrete representation.
+You can get just the same efficiency and effect by using
+<literal>data</literal> instead of <literal>newtype</literal>. If
+there is no overloading involved, then there is more of a case for
+allowing an existentially-quantified <literal>newtype</literal>,
+because the <literal>data</literal> version does carry an
+implementation cost, but single-field existentially quantified
+constructors aren't much use. So the simple restriction (no
+existential stuff on <literal>newtype</literal>) stands, unless there
+are convincing reasons to change it.
</para>
<sect3><title>The context of a type signature</title>
<para>
-Unlike Haskell 1.4, constraints in types do <emphasis>not</emphasis> have to be of
-the form <emphasis>(class type-variables)</emphasis>. Thus, these type signatures
-are perfectly OK
+Unlike Haskell 98, constraints in types do <emphasis>not</emphasis> have to be of
+the form <emphasis>(class type-variable)</emphasis> or
+<emphasis>(class (type-variable type-variable ...))</emphasis>. Thus,
+these type signatures are perfectly OK
<programlisting>
- f :: Eq (m a) => [m a] -> [m a]
g :: Eq [a] => ...
+ g :: Ord (T a ()) => ...
</programlisting>
-This choice recovers principal types, a property that Haskell 1.4 does not have.
</para>
<para>
GHC imposes the following restrictions on the constraints in a type signature.
</programlisting>
(Here, we write the "foralls" explicitly, although the Haskell source
-language omits them; in Haskell 1.4, all the free type variables of an
+language omits them; in Haskell 98, all the free type variables of an
explicit source-language type signature are universally quantified,
except for the class type variables in a class declaration. However,
in GHC, you can give the foralls if you want. See <xref LinkEnd="universal-quantification">).
<emphasis>Each universally quantified type variable
<literal>tvi</literal> must be reachable from <literal>type</literal></emphasis>.
-A type variable is "reachable" if it it is functionally dependent
-(see <xref linkend="functional-dependencies">)
-on the type variables free in <literal>type</literal>.
-The reason for this is that a value with a type that does not obey
-this restriction could not be used without introducing
-ambiguity.
+A type variable <literal>a</literal> is "reachable" if it it appears
+in the same constraint as either a type variable free in in
+<literal>type</literal>, or another reachable type variable.
+A value with a type that does not obey
+this reachability restriction cannot be used without introducing
+ambiguity; that is why the type is rejected.
Here, for example, is an illegal type:
applied to a dictionary for <literal>Eq tv</literal>. The difficulty is that we
can never know which instance of <literal>Eq</literal> to use because we never
get any more information about <literal>tv</literal>.
-
+</para>
+<para>
+Note
+that the reachability condition is weaker than saying that <literal>a</literal> is
+functionally dependendent on a type variable free in
+<literal>type</literal> (see <xref
+linkend="functional-dependencies">). The reason for this is there
+might be a "hidden" dependency, in a superclass perhaps. So
+"reachable" is a conservative approximation to "functionally dependent".
+For example, consider:
+<programlisting>
+ class C a b | a -> b where ...
+ class C a b => D a b where ...
+ f :: forall a b. D a b => a -> a
+</programlisting>
+This is fine, because in fact <literal>a</literal> does functionally determine <literal>b</literal>
+but that is not immediately apparent from <literal>f</literal>'s type.
</para>
</listitem>
<listitem>
instance context2 => C type2 where ...
</programlisting>
-
-"overlap" if <literal>type1</literal> and <literal>type2</literal> unify
-
+"overlap" if <literal>type1</literal> and <literal>type2</literal> unify.
+</para>
+<para>
However, if you give the command line option
<option>-fallow-overlapping-instances</option><indexterm><primary>-fallow-overlapping-instances
option</primary></indexterm> then overlapping instance declarations are permitted.
<title>Type synonyms in the instance head</title>
<para>
-<emphasis>Unlike Haskell 1.4, instance heads may use type
+<emphasis>Unlike Haskell 98, instance heads may use type
synonyms</emphasis>. (The instance "head" is the bit after the "=>" in an instance decl.)
As always, using a type synonym is just shorthand for
writing the RHS of the type synonym definition. For example:
shows, the polymorphic type on the left of the function arrow can be overloaded.
</para>
<para>
-The functions <literal>f3</literal> and <literal>g3</literal> have rank-3 types;
-they have rank-2 types on the left of a function arrow.
+The function <literal>f3</literal> has a rank-3 type;
+it has rank-2 types on the left of a function arrow.
</para>
<para>
GHC allows types of arbitrary rank; you can nest <literal>forall</literal>s
<listitem> <para> On the left of a function arrow </para> </listitem>
<listitem> <para> On the right of a function arrow (see <xref linkend="hoist">) </para> </listitem>
<listitem> <para> As the argument of a constructor, or type of a field, in a data type declaration. For
-example, any of the <literal>f1,f2,f3,g1,g2,g3</literal> above would be valid
+example, any of the <literal>f1,f2,f3,g1,g2</literal> above would be valid
field type signatures.</para> </listitem>
<listitem> <para> As the type of an implicit parameter </para> </listitem>
<listitem> <para> In a pattern type signature (see <xref linkend="scoped-type-variables">) </para> </listitem>
<literal>S</literal> is a type constructor,
</para></listitem>
<listitem><para>
- <literal>t1...tk</literal> are types,
+ The <literal>t1...tk</literal> are types,
</para></listitem>
<listitem><para>
- <literal>vk+1...vn</literal> are type variables which do not occur in any of
+ The <literal>vk+1...vn</literal> are type variables which do not occur in any of
the <literal>ti</literal>, and
</para></listitem>
<listitem><para>
- the <literal>ci</literal> are partial applications of
+ The <literal>ci</literal> are partial applications of
classes of the form <literal>C t1'...tj'</literal>, where the arity of <literal>C</literal>
is exactly <literal>j+1</literal>. That is, <literal>C</literal> lacks exactly one type argument.
</para></listitem>
+<listitem><para>
+ None of the <literal>ci</literal> is <literal>Read</literal>, <literal>Show</literal>,
+ <literal>Typeable</literal>, or <literal>Data</literal>. These classes
+ should not "look through" the type or its constructor. You can still
+ derive these classes for a newtype, but it happens in the usual way, not
+ via this new mechanism.
+</para></listitem>
</itemizedlist>
Then, for each <literal>ci</literal>, the derived instance
declaration is:
the main technical innovations is discussed in "<ulink
url="http://research.microsoft.com/~simonpj/papers/meta-haskell">
Template Meta-programming for Haskell</ulink>" (Proc Haskell Workshop 2002).
+The details of the Template Haskell design are still in flux. Make sure you
+consult the <ulink url="http://www.haskell.org/ghc/docs/latest/html/libraries/index.html">online library reference material</ulink>
+(search for the type ExpQ).
+[Temporary: many changes to the original design are described in
+ <ulink url="http://research.microsoft.com/~simonpj/tmp/notes2.ps">"http://research.microsoft.com/~simonpj/tmp/notes2.ps"</ulink>.
+Not all of these changes are in GHC 6.2.]
</para>
<para> The first example from that paper is set out below as a worked example to help get you started.
First cut and paste the two modules below into "Main.hs" and "Printf.hs":</para>
<programlisting>
+
{- Main.hs -}
module Main where
-- generated at compile time by "pr" and splices it into
-- the argument of "putStrLn".
main = putStrLn ( $(pr "Hello") )
-</programlisting>
-<programlisting>
+
{- Printf.hs -}
module Printf where
-- you intend to use it.
-- Import some Template Haskell syntax
-import Language.Haskell.THSyntax
+import Language.Haskell.TH.Syntax
-- Describe a format string
data Format = D | S | L String
-- Generate Haskell source code from a parsed representation
-- of the format string. This code will be spliced into
-- the module which calls "pr", at compile time.
-gen :: [Format] -> Expr
+gen :: [Format] -> ExpQ
gen [D] = [| \n -> show n |]
gen [S] = [| \s -> s |]
-gen [L s] = string s
+gen [L s] = stringE s
-- Here we generate the Haskell code for the splice
-- from an input format string.
-pr :: String -> Expr
+pr :: String -> ExpQ
pr s = gen (parse s)
</programlisting>
it won't make much sense unless you've read Hughes's paper.
This notation is translated to ordinary Haskell,
using combinators from the
-<ulink url="../base/Control.Arrow.html"><literal>Control.Arrow</literal></ulink>
+<ulink url="../libraries/base/Control.Arrow.html"><literal>Control.Arrow</literal></ulink>
module.
</para>
-<para>The extension adds a new kind of expression for defining arrows,
-of the form <literal>proc pat -> cmd</literal>,
+<para>The extension adds a new kind of expression for defining arrows:
+<screen>
+<replaceable>exp</replaceable><superscript>10</superscript> ::= ...
+ | proc <replaceable>apat</replaceable> -> <replaceable>cmd</replaceable>
+</screen>
where <literal>proc</literal> is a new keyword.
The variables of the pattern are bound in the body of the
<literal>proc</literal>-expression,
which is a new sort of thing called a <firstterm>command</firstterm>.
The syntax of commands is as follows:
<screen>
-cmd ::= exp1 -< exp2
- | exp1 -<< exp2
- | do { cstmt1 .. cstmtn ; cmd }
- | let decls in cmd
- | if exp then cmd1 else cmd2
- | case exp of { calts }
- | cmd1 qop cmd2
- | (| aexp cmd1 .. cmdn |)
- | \ pat1 .. patn -> cmd
- | cmd aexp
- | ( cmd )
-
-cstmt ::= let decls
- | pat <- cmd
- | rec { cstmt1 .. cstmtn }
- | cmd
+<replaceable>cmd</replaceable> ::= <replaceable>exp</replaceable><superscript>10</superscript> -< <replaceable>exp</replaceable>
+ | <replaceable>exp</replaceable><superscript>10</superscript> -<< <replaceable>exp</replaceable>
+ | <replaceable>cmd</replaceable><superscript>0</superscript>
+</screen>
+with <replaceable>cmd</replaceable><superscript>0</superscript> up to
+<replaceable>cmd</replaceable><superscript>9</superscript> defined using
+infix operators as for expressions, and
+<screen>
+<replaceable>cmd</replaceable><superscript>10</superscript> ::= \ <replaceable>apat</replaceable> ... <replaceable>apat</replaceable> -> <replaceable>cmd</replaceable>
+ | let <replaceable>decls</replaceable> in <replaceable>cmd</replaceable>
+ | if <replaceable>exp</replaceable> then <replaceable>cmd</replaceable> else <replaceable>cmd</replaceable>
+ | case <replaceable>exp</replaceable> of { <replaceable>calts</replaceable> }
+ | do { <replaceable>cstmt</replaceable> ; ... <replaceable>cstmt</replaceable> ; <replaceable>cmd</replaceable> }
+ | <replaceable>fcmd</replaceable>
+
+<replaceable>fcmd</replaceable> ::= <replaceable>fcmd</replaceable> <replaceable>aexp</replaceable>
+ | ( <replaceable>cmd</replaceable> )
+ | (| <replaceable>aexp</replaceable> <replaceable>cmd</replaceable> ... <replaceable>cmd</replaceable> |)
+
+<replaceable>cstmt</replaceable> ::= let <replaceable>decls</replaceable>
+ | <replaceable>pat</replaceable> <- <replaceable>cmd</replaceable>
+ | rec { <replaceable>cstmt</replaceable> ; ... <replaceable>cstmt</replaceable> [;] }
+ | <replaceable>cmd</replaceable>
</screen>
+where <replaceable>calts</replaceable> are like <replaceable>alts</replaceable>
+except that the bodies are commands instead of expressions.
+</para>
+
+<para>
Commands produce values, but (like monadic computations)
may yield more than one value,
or none, and may do other things as well.
</programlisting>
so we can use it to build commands:
<programlisting>
-expr' = proc x ->
+expr' = proc x -> do
returnA -< x
<+> do
symbol Plus -< ()
y <- term -< ()
expr' -< x - y
</programlisting>
+(The <literal>do</literal> on the first line is needed to prevent the first
+<literal><+> ...</literal> from being interpreted as part of the
+expression on the previous line.)
This is equivalent to
<programlisting>
expr' = (proc x -> returnA -< x)
Although only GHC implements arrow notation directly,
there is also a preprocessor
(available from the
-<ulink url="http://www.haskell.org/arrows/">arrows web page></ulink>)
+<ulink url="http://www.haskell.org/arrows/">arrows web page</ulink>)
that translates arrow notation into Haskell 98
for use with other Haskell systems.
You would still want to check arrow programs with GHC;
<para>The DEPRECATED pragma lets you specify that a particular
function, class, or type, is deprecated. There are two
- forms.</para>
+ forms.
<itemizedlist>
<listitem>
message.</para>
</listitem>
</itemizedlist>
-
+ Any use of the deprecated item, or of anything from a deprecated
+ module, will be flagged with an appropriate message. However,
+ deprecations are not reported for
+ (a) uses of a deprecated function within its defining module, and
+ (b) uses of a deprecated function in an export list.
+ The latter reduces spurious complaints within a library
+ in which one module gathers together and re-exports
+ the exports of several others.
+ </para>
<para>You can suppress the warnings with the flag
<option>-fno-warn-deprecations</option>.</para>
</sect2>
<para>A <literal>SPECIALIZE</literal> pragma for a function can
be put anywhere its type signature could be put.</para>
-<para>A <literal>SPECIALIZE</literal> has the effect of generating (a) a specialised
-version of the function and (b) a rewrite rule (see <xref linkend="rules">) that
-rewrites a call to the un-specialised function into a call to the specialised
-one. You can, instead, provide your own specialised function and your own rewrite rule.
-For example, suppose that:
-<programlisting>
- genericLookup :: Ord a => Table a b -> a -> b
- intLookup :: Table Int b -> Int -> b
-</programlisting>
-where <literal>intLookup</literal> is an implementation of <literal>genericLookup</literal>
-that works very fast for keys of type <literal>Int</literal>. Then you can write the rule
-<programlisting>
- {-# RULES "intLookup" genericLookup = intLookup #-}
-</programlisting>
-(see <xref linkend="rule-spec">). It is <emphasis>Your
- Responsibility</emphasis> to make sure that
- <function>intLookup</function> really behaves as a specialised
- version of <function>genericLookup</function>!!!</para>
+ <para>A <literal>SPECIALIZE</literal> has the effect of generating
+ (a) a specialised version of the function and (b) a rewrite rule
+ (see <xref linkend="rewrite-rules">) that rewrites a call to the
+ un-specialised function into a call to the specialised one.</para>
- <para>An example in which using <literal>RULES</literal> for
- specialisation will Win Big:
+ <para>In earlier versions of GHC, it was possible to provide your own
+ specialised function for a given type:
<programlisting>
- toDouble :: Real a => a -> Double
- toDouble = fromRational . toRational
-
- {-# RULES "toDouble/Int" toDouble = i2d #-}
- i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly
+{-# SPECIALIZE hammeredLookup :: [(Int, value)] -> Int -> value = intLookup #-}
</programlisting>
- The <function>i2d</function> function is virtually one machine
- instruction; the default conversion—via an intermediate
- <literal>Rational</literal>—is obscenely expensive by
- comparison.</para>
+ This feature has been removed, as it is now subsumed by the
+ <literal>RULES</literal> pragma (see <xref linkend="rule-spec">).</para>
</sect2>
</sect2>
-
+ <sect2 id="unpack-pragma">
+ <title>UNPACK pragma</title>
+
+ <indexterm><primary>UNPACK</primary></indexterm>
+
+ <para>The <literal>UNPACK</literal> indicates to the compiler
+ that it should unpack the contents of a constructor field into
+ the constructor itself, removing a level of indirection. For
+ example:</para>
+
+<ProgramListing>
+data T = T {-# UNPACK #-} !Float
+ {-# UNPACK #-} !Float
+</ProgramListing>
+
+ <para>will create a constructor <literal>T</literal> containing
+ two unboxed floats. This may not always be an optimisation: if
+ the <Function>T</Function> constructor is scrutinised and the
+ floats passed to a non-strict function for example, they will
+ have to be reboxed (this is done automatically by the
+ compiler).</para>
+
+ <para>Unpacking constructor fields should only be used in
+ conjunction with <option>-O</option>, in order to expose
+ unfoldings to the compiler so the reboxing can be removed as
+ often as possible. For example:</para>
+
+<ProgramListing>
+f :: T -> Float
+f (T f1 f2) = f1 + f2
+</ProgramListing>
+
+ <para>The compiler will avoid reboxing <Function>f1</Function>
+ and <Function>f2</Function> by inlining <Function>+</Function>
+ on floats, but only when <option>-O</option> is on.</para>
+
+ <para>Any single-constructor data is eligible for unpacking; for
+ example</para>
+
+<ProgramListing>
+data T = T {-# UNPACK #-} !(Int,Int)
+</ProgramListing>
+
+ <para>will store the two <literal>Int</literal>s directly in the
+ <Function>T</Function> constructor, by flattening the pair.
+ Multi-level unpacking is also supported:</para>
+
+<ProgramListing>
+data T = T {-# UNPACK #-} !S
+data S = S {-# UNPACK #-} !Int {-# UNPACK #-} !Int
+</ProgramListing>
+
+ <para>will store two unboxed <literal>Int#</literal>s
+ directly in the <Function>T</Function> constructor. The
+ unpacker can see through newtypes, too.</para>
+
+ <para>If a field cannot be unpacked, you will not get a warning,
+ so it might be an idea to check the generated code with
+ <option>-ddump-simpl</option>.</para>
+
+ <para>See also the <option>-funbox-strict-fields</option> flag,
+ which essentially has the effect of adding
+ <literal>{-# UNPACK #-}</literal> to every strict
+ constructor field.</para>
+ </sect2>
</sect1>
<para>
Rewrite rules can be used to get the same effect as a feature
-present in earlier version of GHC:
+present in earlier versions of GHC.
+For example, suppose that:
<programlisting>
- {-# SPECIALIZE fromIntegral :: Int8 -> Int16 = int8ToInt16 #-}
+genericLookup :: Ord a => Table a b -> a -> b
+intLookup :: Table Int b -> Int -> b
</programlisting>
-This told GHC to use <function>int8ToInt16</function> instead of <function>fromIntegral</function> whenever
-the latter was called with type <literal>Int8 -> Int16</literal>. That is, rather than
-specialising the original definition of <function>fromIntegral</function> the programmer is
-promising that it is safe to use <function>int8ToInt16</function> instead.
-</para>
-
-<para>
-This feature is no longer in GHC. But rewrite rules let you do the
-same thing:
+where <function>intLookup</function> is an implementation of
+<function>genericLookup</function> that works very fast for
+keys of type <literal>Int</literal>. You might wish
+to tell GHC to use <function>intLookup</function> instead of
+<function>genericLookup</function> whenever the latter was called with
+type <literal>Table Int b -> Int -> b</literal>.
+It used to be possible to write
<programlisting>
-{-# RULES
- "fromIntegral/Int8/Int16" fromIntegral = int8ToInt16
-#-}
+{-# SPECIALIZE genericLookup :: Table Int b -> Int -> b = intLookup #-}
</programlisting>
-This slightly odd-looking rule instructs GHC to replace <function>fromIntegral</function>
-by <function>int8ToInt16</function> <emphasis>whenever the types match</emphasis>. Speaking more operationally,
-GHC adds the type and dictionary applications to get the typed rule
+This feature is no longer in GHC, but rewrite rules let you do the same thing:
<programlisting>
-forall (d1::Integral Int8) (d2::Num Int16) .
- fromIntegral Int8 Int16 d1 d2 = int8ToInt16
+{-# RULES "genericLookup/Int" genericLookup = intLookup #-}
</programlisting>
-What is more,
-this rule does not need to be in the same file as fromIntegral,
-unlike the <literal>SPECIALISE</literal> pragmas which currently do (so that they
+This slightly odd-looking rule instructs GHC to replace
+<function>genericLookup</function> by <function>intLookup</function>
+<emphasis>whenever the types match</emphasis>.
+What is more, this rule does not need to be in the same
+file as <function>genericLookup</function>, unlike the
+<literal>SPECIALIZE</literal> pragmas which currently do (so that they
have an original definition available to specialise).
</para>
+<para>It is <emphasis>Your Responsibility</emphasis> to make sure that
+<function>intLookup</function> really behaves as a specialised version
+of <function>genericLookup</function>!!!</para>
+
+<para>An example in which using <literal>RULES</literal> for
+specialisation will Win Big:
+
+<programlisting>
+toDouble :: Real a => a -> Double
+toDouble = fromRational . toRational
+
+{-# RULES "toDouble/Int" toDouble = i2d #-}
+i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly
+</programlisting>
+
+The <function>i2d</function> function is virtually one machine
+instruction; the default conversion—via an intermediate
+<literal>Rational</literal>—is obscenely expensive by
+comparison.
+</para>
+
</sect2>
<sect2>