Hello,<br><br>You might already know this, but in case you don'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 <<a href="mailto:blais@furius.ca">blais@furius.ca</a>> 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>
"rst-literals" 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>
CLASS Employee (<br>
firstname VARCHAR,<br>
lastname VARCHAR<br>
)<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't like to have to<br>
prefix every line of code I write, despite the help that<br>
Emacs' 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>
.SUFFIXES: .rst .hs<br>
<br>
all: chap6<br>
<br>
.rst.hs:<br>
rst-literals $< > $@<br>
<br>
chap6: chap6.hs<br>
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 "#line <filename> <lineno>", 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>
Exercises from Hutton book, Chapter 6<br>
===========================================<br>
<br>
.. contents::<br>
..<br>
1 Introduction<br>
2 Exercise 1<br>
3 Exercise 2<br>
4 Exercise 3<br>
5 Exercise 4<br>
6 Exercise 5<br>
7 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>
myexp :: Int -> Int -> Int<br>
myexp b 0 = 1<br>
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 "#!example", so that<br>
they don't get included in the output when only the<br>
"default" literal blocks get extracted. See rst-literals<br>
docstring for details.)<br>
<br>
Length::<br>
<br>
#!example<br>
1 + (length [2, 3])<br>
1 + 1 + (length [3])<br>
1 + 1 + (1)<br>
3<br>
<br>
Drop::<br>
<br>
#!example<br>
drop 3 [1, 2, 3, 4, 5]<br>
[] ++ drop 3 [2, 3, 4, 5]<br>
[] ++ [] ++ drop 3 [3, 4, 5]<br>
[] ++ [] ++ [] ++ [4, 5]<br>
[4, 5]<br>
<br>
Init::<br>
<br>
#!example<br>
init [1, 2, 3]<br>
[1] ++ init [2, 3]<br>
[1] ++ [2] ++ init [3]<br>
[1] ++ [2] ++ []<br>
[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>
and' :: [Bool] -> Bool<br>
and' [x] = x<br>
and' (x:xs) = x && and' xs<br>
<br>
concat' :: [[a]] -> [a]<br>
concat' [] = []<br>
concat' (x:xs) = x ++ concat' xs<br>
<br>
replicate' :: Int -> a -> [a]<br>
replicate' 0 x = []<br>
replicate' (n+1) x = (x : replicate' n x)<br>
<br>
select' :: [a] -> Int -> a<br>
select' (x:xs) 0 = x<br>
select' (x:xs) (n+1) = select' xs n<br>
<br>
elem' :: Eq a => a -> [a] -> Bool<br>
elem' _ [] = False<br>
elem' y (x:xs) | x == y = True<br>
| otherwise = elem' y xs<br>
<br>
Exercise 4<br>
==========<br>
<br>
The exercise asked to implement a function to merge two lists::<br>
<br>
merge :: Ord a => [a] -> [a] -> [a]<br>
merge xs [] = xs<br>
merge [] xs = xs<br>
merge (x:xs) (y:ys) | x < y = (x : merge xs (y:ys))<br>
| otherwise = (y : merge (x:xs) ys)<br>
<br>
<br>
Exercise 5<br>
==========<br>
::<br>
<br>
msort :: Ord a => [a] -> [a]<br>
msort [] = []<br>
msort [x] = [x] -- This is necessary to end the recursion.<br>
msort xs = merge (msort (fst hh)) (msort (snd hh))<br>
where hh = halve xs<br>
<br>
halve :: [a] -> ([a], [a])<br>
halve xs = (take n xs, drop n xs)<br>
where n = (length xs) `div` 2<br>
<br>
Some main program::<br>
<br>
main = (putStrLn . show) (halve [1..17])<br>
<br>
<br>
Exercise 6<br>
==========<br>
<br>
(Too basic, I didn'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>