[Haskell-cafe] Literal programming in Haskell with rst-literals

Abhay Parvate abhay.parvate at gmail.com
Mon Jun 23 07:20:30 EDT 2008


Hello,

You might already know this, but in case you don't: there is another
literate style:

... non-code ...
\begin{code}
... code ...
\end{code}
... non-code ...

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.)

I hope I am not being redundant!
Abhay


On Sat, Jun 21, 2008 at 11:48 PM, Martin Blais <blais at furius.ca> wrote:

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


More information about the Haskell-Cafe mailing list