+ <para>The type in a SPECIALIZE pragma can be any type that is less
+ polymorphic than the type of the original function. In concrete terms,
+ if the original function is <literal>f</literal> then the pragma
+<programlisting>
+ {-# SPECIALIZE f :: <type> #-}
+</programlisting>
+ is valid if and only if the defintion
+<programlisting>
+ f_spec :: <type>
+ f_spec = f
+</programlisting>
+ is valid. Here are some examples (where we only give the type signature
+ for the original function, not its code):
+<programlisting>
+ f :: Eq a => a -> b -> b
+ {-# SPECIALISE f :: Int -> b -> b #-}
+
+ g :: (Eq a, Ix b) => a -> b -> b
+ {-# SPECIALISE g :: (Eq a) => a -> Int -> Int #-}
+
+ h :: Eq a => a -> a -> a
+ {-# SPECIALISE h :: (Eq a) => [a] -> [a] -> [a] #-}
+</programlisting>
+The last of these examples will generate a
+RULE with a somewhat-complex left-hand side (try it yourself), so it might not fire very
+well. If you use this kind of specialisation, let us know how well it works.
+</para>
+
+<para>A <literal>SPECIALIZE</literal> pragma can optionally be followed with a
+<literal>INLINE</literal> or <literal>NOINLINE</literal> pragma, optionally
+followed by a phase, as described in <xref linkend="inline-noinline-pragma"/>.
+The <literal>INLINE</literal> pragma affects the specialised verison of the
+function (only), and applies even if the function is recursive. The motivating
+example is this:
+<programlisting>
+-- A GADT for arrays with type-indexed representation
+data Arr e where
+ ArrInt :: !Int -> ByteArray# -> Arr Int
+ ArrPair :: !Int -> Arr e1 -> Arr e2 -> Arr (e1, e2)
+
+(!:) :: Arr e -> Int -> e
+{-# SPECIALISE INLINE (!:) :: Arr Int -> Int -> Int #-}
+{-# SPECIALISE INLINE (!:) :: Arr (a, b) -> Int -> (a, b) #-}
+(ArrInt _ ba) !: (I# i) = I# (indexIntArray# ba i)
+(ArrPair _ a1 a2) !: i = (a1 !: i, a2 !: i)
+</programlisting>
+Here, <literal>(!:)</literal> is a recursive function that indexes arrays
+of type <literal>Arr e</literal>. Consider a call to <literal>(!:)</literal>
+at type <literal>(Int,Int)</literal>. The second specialisation will fire, and
+the specialised function will be inlined. It has two calls to
+<literal>(!:)</literal>,
+both at type <literal>Int</literal>. Both these calls fire the first
+specialisation, whose body is also inlined. The result is a type-based
+unrolling of the indexing function.</para>
+<para>Warning: you can make GHC diverge by using <literal>SPECIALISE INLINE</literal>
+on an ordinarily-recursive function.</para>
+
+ <para>Note: In earlier versions of GHC, it was possible to provide your own