module LiterateHaskellDemo where

Falderal in Literate Haskell

This file demonstrates how Falderal tests can be embedded in a Bird-style Literate Haskell source file.

This module was written by Chris Pressey. It is hereby placed in the public domain.

The Function to be Tested

A function taking Strings to Strings.

everySecond :: String -> String
everySecond [] = []
everySecond [a] = []
everySecond "silly" = head []
everySecond "silliness" = error "silliness"
everySecond "supercilious" = error "not\non\nmy\nwatch"
everySecond "suoilic\nrepus" = "not\non\nmy\nwatch"
everySecond (a : b : rest) = (b : everySecond rest)

A function taking Strings to Lists of Booleans. We test this by composing it with show.

parseBits :: String -> [Bool]
parseBits [] = []
parseBits ('0':rest) = (False:parseBits rest)
parseBits ('1':rest) = (True:parseBits rest)
parseBits ('\n':rest) = parseBits rest
showParseBits = show . parseBits

Pragmas are able to extend over multiple lines, just like anything else. In addition, spaces between words (outside of quotes strings) are not significant; you can have as many as you like.

 Functionality "Retain every second character"
 is         implemented
 by Haskell function LiterateHaskellDemo:everySecond

Tests for everySecond

 Tests for functionality "Retain every second character"

Every second symbol in the string is retained.

Falderal
= adrl

Works for odd-length strings, too.

Bandana
= adn

If there aren't even two symbols in the string, the result is the empty string. Note that we have to precede the expected empty string with "= ", that is, an equals sign and a space.

A
= 

This is an intentionally failing test, to demonstrate how Falderal will present it.

Something
= Anything

A test that expects an exception.

silly
? Prelude.head: empty list

Another test that expects an exception.

silliness
? silliness

The expected text of an exception can extend over several lines.

supercilious
? not
? on
? my
? watch

The input and expected text and extend over several lines, too.

suoilic
repus
= not
= on
= my
= watch

Another intentionally failing test to demonstrate how Falderal will present expecting an exception and not getting one.

ridiculous
? Prelude.head: empty list

Tests for parseBits

 Tests for Haskell function LiterateHaskellDemo:showParseBits

We can test functions of type

f :: (Show a) => String -> a

by simply composing them with show, i.e.

show . f :: String -> String
01
= [False,True]

An intentionally failing test to demonstrate that it is important to get the formatting of the output right, when testing with show.

01
= [False, True]

= []

Input can consist of multiple lines of text. These are joined together with intervening newline characters.

00
11
= [False,False,True,True]

An intentionally failing test to demonstrate show what a failure looks like on multi-line input.

01
10
= [False,False,True,True]

If we have a set of tests where the tests after the first one have no descriptions of their own, we can take this to suggest they are all testing the same thing. In this case, the literal text that is displayed when any of them fails is the text that comes before the first of them, annotated with the number of the test in the set that failed. The intentionally-failing third test below demonstrates this.

00
= [False,False]
000
= [False,False,False]
0000
= [False,False,False,Flse]