[project @ 2006-01-12 10:04:36 by simonmar]
[ghc-hetmet.git] / ghc / docs / users_guide / glasgow_exts.xml
index 620f8b6..4d7577d 100644 (file)
@@ -1866,16 +1866,21 @@ For example, this is OK:
 
 <listitem>
 <para>All of the types in the <emphasis>context</emphasis> of
-an instance declaration <emphasis>must</emphasis> be type variables.
+an instance declaration <emphasis>must</emphasis> be type variables, and
+there must be no repeated type variables in any one constraint.
 Thus
 <programlisting>
 instance C a b => Eq (a,b) where ...
 </programlisting>
 is OK, but
 <programlisting>
-instance C Int b => Foo b where ...
+instance C Int b => Foo [b] where ...
 </programlisting>
-is not OK.
+is not OK (because of the non-type-variable <literal>Int</literal> in the context), and nor is
+<programlisting>
+instance C b b => Foo [b] where ...
+</programlisting>
+(because of the repeated type variable).
 </para>
 </listitem>
 </orderedlist>
@@ -4902,7 +4907,7 @@ key_function :: Int -> String -> (Bool, Double)
       for the original function, not its code):
 <programlisting>
   f :: Eq a => a -> b -> b
-  {-# SPECIALISE g :: Int -> b -> b #-}
+  {-# SPECIALISE f :: Int -> b -> b #-}
 
   g :: (Eq a, Ix b) => a -> b -> b
   {-# SPECIALISE g :: (Eq a) => a -> Int -> Int #-}
@@ -4915,6 +4920,35 @@ RULE with a somewhat-complex left-hand side (try it yourself), so it might not f
 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
       specialised function for a given type: