[project @ 2003-01-09 11:39:20 by simonmar]
[ghc-hetmet.git] / ghc / docs / users_guide / glasgow_exts.sgml
index 7dff721..6b3bd13 100644 (file)
@@ -3218,6 +3218,9 @@ Template Meta-programming for Haskell</ulink>", in
 Proc Haskell Workshop 2002.
 </para>
 
+<para> The first example from that paper is set out below as a worked example to help get you started. 
+</para>
+
 <para>
 The documentation here describes the realisation in GHC.  (It's rather sketchy just now;
 Tim Sheard is going to expand it.)
@@ -3293,6 +3296,13 @@ Tim Sheard is going to expand it.)
     <listitem><para>
            The flag <literal>-ddump-splices</literal> shows the expansion of all top-level splices as they happen.
    </para></listitem>
+    <listitem><para>
+           If you are building GHC from source, you need at least a stage-2 bootstrap compiler to
+             run Template Haskell.  A stage-1 compiler will reject the TH constructs.  Reason: TH
+             compiles and runs a program, and then looks at the result.  So it's important that
+             the program it compiles produces results whose representations are identical to
+             those of the compiler itself.
+   </para></listitem>
 </itemizedlist>
 </para>
 <para> Template Haskell works in any mode (<literal>--make</literal>, <literal>--interactive</literal>,
@@ -3301,6 +3311,73 @@ Tim Sheard is going to expand it.)
 </para>
 </sect2>
  
+<sect2>  <title> A Template Haskell Worked Example </title>
+<para>To help you get over the confidence barrier, try out this skeletal worked example.
+  First cut and paste the two modules below into "Main.hs" and "Printf.hs":</para>
+
+<programlisting>
+{- Main.hs -}
+module Main where
+
+-- Import our template "pr"
+import Printf ( pr )
+
+-- The splice operator $ takes the Haskell source code
+-- 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
+
+-- Skeletal printf from the paper.
+-- It needs to be in a separate module to the one where
+-- you intend to use it.
+
+-- Import some Template Haskell syntax
+import Language.Haskell.THSyntax
+
+-- Describe a format string
+data Format = D | S | L String
+
+-- Parse a format string.  This is left largely to you
+-- as we are here interested in building our first ever
+-- Template Haskell program and not in building printf.
+parse :: String -> [Format]
+parse s   = [ L s ]
+
+-- 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 [D]   = [| \n -> show n |]
+gen [S]   = [| \s -> s |]
+gen [L s] = string s
+
+-- Here we generate the Haskell code for the splice
+-- from an input format string.
+pr :: String -> Expr
+pr s      = gen (parse s)
+</programlisting>
+
+<para>Now run the compiler (here we are using a "stage three" build of GHC, at a Cygwin prompt on Windows):
+</para>
+<programlisting>
+ghc/compiler/stage3/ghc-inplace --make -fglasgow-exts -package haskell-src main.hs -o main.exe
+</programlisting>
+
+<para>Run "main.exe" and here is your output:
+</para>
+
+<programlisting>
+$ ./main
+Hello
+</programlisting>
+
+</sect2>
 </sect1>
 
 <!-- ==================== ASSERTIONS =================  -->
@@ -3527,11 +3604,14 @@ hammeredLookup :: Ord key => [(key, value)] -> key -> value
 {-# SPECIALIZE hammeredLookup :: [(Widget, value)] -> Widget -> value #-}
 </programlisting>
 
+      <para>A <literal>SPECIALIZE</literal> pragma for a function can
+      be put anywhere its type signature could be put.</para>
+
       <para>To get very fancy, you can also specify a named function
       to use for the specialised value, as in:</para>
 
 <programlisting>
-{-# RULES hammeredLookup = blah #-}
+{-# RULES "hammeredLookup" hammeredLookup = blah #-}
 </programlisting>
 
       <para>where <literal>blah</literal> is an implementation of
@@ -3554,7 +3634,7 @@ hammeredLookup :: Ord key => [(key, value)] -> key -> value
 toDouble :: Real a => a -> Double
 toDouble = fromRational . toRational
 
-{-# SPECIALIZE toDouble :: Int -> Double = i2d #-}
+{-# RULES "toDouble/Int" toDouble = i2d #-}
 i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly
 </programlisting>
 
@@ -3563,9 +3643,6 @@ i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly
       <literal>Rational</literal>&mdash;is obscenely expensive by
       comparison.</para>
 
-      <para>A <literal>SPECIALIZE</literal> pragma for a function can
-      be put anywhere its type signature could be put.</para>
-
     </sect2>
 
 <sect2 id="specialize-instance-pragma">