Hello,<br><br>You might already know this, but in case you don&#39;t: there is another literate style:<br><br>... non-code ...<br>\begin{code}<br>... code ...<br>\end{code}<br>... non-code ...<br><br>in which you do not put prefixes to each line. (In fact the standard says somewhere it is not recommended to mix the two styles if I remember right.)<br>
<br>I hope I am not being redundant!<br>Abhay<br><br><br><div class="gmail_quote">On Sat, Jun 21, 2008 at 11:48 PM, Martin Blais &lt;<a href="mailto:blais@furius.ca">blais@furius.ca</a>&gt; wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
Hello Haskell community!<br>
<br>
I just did a marginally cool thing and I wanted to share it<br>
with you.<br>
<br>
&quot;rst-literals&quot; is a small program I wrote a while ago in<br>
order to write documents in reStructuredText format that<br>
would embed SQL code for data models in them, a form of<br>
literal programming for SQL if you will; I would describe my<br>
needs for the schema in prose, and reST literal-blocks were<br>
used to embed SQL code, blocks that look like this::<br>
<br>
 &nbsp;CLASS Employee (<br>
 &nbsp; &nbsp; firstname VARCHAR,<br>
 &nbsp; &nbsp; lastname VARCHAR<br>
 &nbsp;)<br>
<br>
I wrote the script to be entirely generic: it parses the<br>
reST documents using the docutils code and outputs only the<br>
literal-blocks, with indentation removed; you can then run<br>
your favourite interpreter/compiler on the result (in that<br>
case, psql to initialize a database).<br>
<br>
Recently, while experimenting with Haskell, I started using<br>
both the literal (.lhs) and non-literal (.hs) styles of<br>
Haskell input, and I found the literal style a bit<br>
unpleasant to use, in particular, I don&#39;t like to have to<br>
prefix every line of code I write, despite the help that<br>
Emacs&#39; haskell-mode provides.<br>
<br>
So I tried pulling a similar trick and embedding Haskell<br>
code in literal-blocks within reST documents, extracting<br>
that code using rst-literals, and it turns out that it works<br>
like a charm. Here is an example makefile for doing this::<br>
<br>
 &nbsp;.SUFFIXES: .rst .hs<br>
<br>
 &nbsp;all: chap6<br>
<br>
 &nbsp;.rst.hs:<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rst-literals $&lt; &gt; $@<br>
<br>
 &nbsp;chap6: chap6.hs<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ghc --make chap6.hs<br>
<br>
An example reST document with some embedded Haskell code<br>
follows this email. Note that since rst-literals is using<br>
the docutils parser, you can make use of all of the<br>
recursive reST syntax, sections, bulleted items and much<br>
more. Only the literal-blocks are extracted, anywhere they<br>
appear. You can also easily process the reST source into<br>
HTML pages or LaTeX documents using the tools that come with<br>
docutils.<br>
<br>
You can find rst-literals here:<br>
<a href="http://furius.ca/pubcode/" target="_blank">http://furius.ca/pubcode/</a><br>
<br>
Enjoy,<br>
<br>
<br>
<br>
<br>
--<br>
Martin<br>
<br>
P.S. If there is a way to output cpp-like directives for<br>
GHC, like &quot;#line &lt;filename&gt; &lt;lineno&gt;&quot;, it would be easy to<br>
modify rst-literals to generate those, so that compilation<br>
errors could refer to the source reST document instead of<br>
the extracted source.<br>
<br>
<br>
<br>
chap6.hs:<br>
----------------------------------------------------------------------<br>
<br>
===========================================<br>
 &nbsp; Exercises from Hutton book, Chapter 6<br>
===========================================<br>
<br>
.. contents::<br>
..<br>
 &nbsp; &nbsp;1 &nbsp;Introduction<br>
 &nbsp; &nbsp;2 &nbsp;Exercise 1<br>
 &nbsp; &nbsp;3 &nbsp;Exercise 2<br>
 &nbsp; &nbsp;4 &nbsp;Exercise 3<br>
 &nbsp; &nbsp;5 &nbsp;Exercise 4<br>
 &nbsp; &nbsp;6 &nbsp;Exercise 5<br>
 &nbsp; &nbsp;7 &nbsp;Exercise 6<br>
<br>
<br>
Introduction<br>
============<br>
<br>
Bla bla bla blablablablablabla bla bla blabla. Bla bla bla<br>
blablablablablabla bla bla blabla. Bla bla bla blablablablablabla bla<br>
bla blabla. Bla bla bla blablablablablabla bla bla blabla. Bla bla bla<br>
blablablablablabla bla bla blabla. Bla bla bla blablablablablabla bla<br>
bla blabla.<br>
<br>
<br>
Exercise 1<br>
==========<br>
::<br>
<br>
 &nbsp;myexp :: Int -&gt; Int -&gt; Int<br>
 &nbsp;myexp b 0 = 1<br>
 &nbsp;myexp b (n+1) = b * (myexp b n)<br>
<br>
<br>
Exercise 2<br>
==========<br>
<br>
(Exercise 2 consisted in derivations, so we mark the literal<br>
blocks as another type of block with &quot;#!example&quot;, so that<br>
they don&#39;t get included in the output when only the<br>
&quot;default&quot; literal blocks get extracted. See rst-literals<br>
docstring for details.)<br>
<br>
Length::<br>
<br>
 &nbsp; &nbsp;#!example<br>
 &nbsp; &nbsp;1 + (length [2, 3])<br>
 &nbsp; &nbsp;1 + 1 + (length [3])<br>
 &nbsp; &nbsp;1 + 1 + (1)<br>
 &nbsp; &nbsp;3<br>
<br>
Drop::<br>
<br>
 &nbsp;#!example<br>
 &nbsp;drop 3 [1, 2, 3, 4, 5]<br>
 &nbsp;[] ++ drop 3 [2, 3, 4, 5]<br>
 &nbsp;[] ++ [] ++ drop 3 [3, 4, 5]<br>
 &nbsp;[] ++ [] ++ [] ++ [4, 5]<br>
 &nbsp;[4, 5]<br>
<br>
Init::<br>
<br>
 &nbsp;#!example<br>
 &nbsp;init [1, 2, 3]<br>
 &nbsp;[1] ++ init [2, 3]<br>
 &nbsp;[1] ++ [2] ++ init [3]<br>
 &nbsp;[1] ++ [2] ++ []<br>
 &nbsp;[1, 2]<br>
<br>
<br>
Exercise 3<br>
==========<br>
<br>
These are alternate versions of the example functions defined in the<br>
text::<br>
<br>
 &nbsp;and&#39; :: [Bool] -&gt; Bool<br>
 &nbsp;and&#39; [x] = x<br>
 &nbsp;and&#39; (x:xs) = x &amp;&amp; and&#39; xs<br>
<br>
 &nbsp;concat&#39; :: [[a]] -&gt; [a]<br>
 &nbsp;concat&#39; [] = []<br>
 &nbsp;concat&#39; (x:xs) = x ++ concat&#39; xs<br>
<br>
 &nbsp;replicate&#39; :: Int -&gt; a -&gt; [a]<br>
 &nbsp;replicate&#39; 0 x = []<br>
 &nbsp;replicate&#39; (n+1) x = (x : replicate&#39; n x)<br>
<br>
 &nbsp;select&#39; :: [a] -&gt; Int -&gt; a<br>
 &nbsp;select&#39; (x:xs) 0 = x<br>
 &nbsp;select&#39; (x:xs) (n+1) = select&#39; xs n<br>
<br>
 &nbsp;elem&#39; :: Eq a =&gt; a -&gt; [a] -&gt; Bool<br>
 &nbsp;elem&#39; _ [] = False<br>
 &nbsp;elem&#39; y (x:xs) | x == y = True<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | otherwise = elem&#39; y xs<br>
<br>
Exercise 4<br>
==========<br>
<br>
The exercise asked to implement a function to merge two lists::<br>
<br>
 &nbsp;merge :: Ord a =&gt; [a] -&gt; [a] -&gt; [a]<br>
 &nbsp;merge xs [] = xs<br>
 &nbsp;merge [] xs = xs<br>
 &nbsp;merge (x:xs) (y:ys) | x &lt; y = (x : merge xs (y:ys))<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| otherwise = (y : merge (x:xs) ys)<br>
<br>
<br>
Exercise 5<br>
==========<br>
::<br>
<br>
 &nbsp;msort :: Ord a =&gt; [a] -&gt; [a]<br>
 &nbsp;msort [] = []<br>
 &nbsp;msort [x] = [x] -- This is necessary to end the recursion.<br>
 &nbsp;msort xs = merge (msort (fst hh)) (msort (snd hh))<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; where hh = halve xs<br>
<br>
 &nbsp;halve :: [a] -&gt; ([a], [a])<br>
 &nbsp;halve xs = (take n xs, drop n xs)<br>
 &nbsp; &nbsp; &nbsp;where n = (length xs) `div` 2<br>
<br>
Some main program::<br>
<br>
 &nbsp;main = (putStrLn . show) (halve [1..17])<br>
<br>
<br>
Exercise 6<br>
==========<br>
<br>
(Too basic, I didn&#39;t bother.)<br>
<br>
----------------------------------------------------------------------<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br>