[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