Andrew Rock
School of Information and Communication Technology
Griffith University
Nathan, Queensland, 4111, Australia
a.rock@griffith.edu.au
Abstract
This document lists and describes the libraries developed for and
common to the various systems I have developed in Haskell1 , including the implementation of all functions.
Contents
1 Introduction
2 Installation
3 Util.Args
3.1 Maintenance notes . . . . .
3.2 Language tweaks . . . . . .
3.3 Data types . . . . . . . . .
3.4 Empty options . . . . . . .
3.5 Option detection . . . . . .
3.6 Adding and deleting options
3.7 Looking up options . . . . .
3.8 Filename globbing . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
5
5
5
5
5
6
6
4 Util.Errors
4.1 Maintenance notes . . . . . . . . . . . . .
4.2 Warning and error data type . . . . . . .
4.3 Warning and error category type class . .
4.4 Data types . . . . . . . . . . . . . . . . .
4.5 Returning successfully, failing or warning
4.6 Instances . . . . . . . . . . . . . . . . . .
4.6.1 Functor . . . . . . . . . . . . . . .
4.6.2 Applicative . . . . . . . . . . . . .
4.6.3 Monad . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
6
6
6
6
6
6
6
7
7
5 Util.Open
5.1 Maintenance notes
5.2 System specifics . .
5.3 Tests . . . . . . . .
5.4 Opening a URL . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7 Util.Time
7.1 Maintenance notes . . . . . . . . . . .
7.2 Data types . . . . . . . . . . . . . . .
7.3 Time conversions . . . . . . . . . . . .
7.4 Getting the current time . . . . . . . .
7.5 Format strings . . . . . . . . . . . . .
7.6 Formatting times . . . . . . . . . . . .
7.7 Formated current time . . . . . . . . .
7.8 Formated file modification time . . . .
7.9 Overloading for old/new time systems
7.10 Instances . . . . . . . . . . . . . . . .
7.10.1 LegacyTimes . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
8
8
8
8
8
8
8
8
8
9
9
8 Control.Check
8.1 Maintenance notes
8.2 Data type . . . . .
8.3 Sequencing checks
8.4 Parallel checks . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9
9
9
9
9
9 Control.List
9.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
9.2 Backwards map . . . . . . . . . . . . . . . . . . . . .
9
9
9
10 Control.Map
10.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
10.2 lookupGuard . . . . . . . . . . . . . . . . . . . . . .
9
9
10
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
10
10
10
10
10
11
11
12
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
7
7
11 Data.List
11.1 Maintenance notes . . .
11.2 Language tweaks . . . .
11.3 Sorting . . . . . . . . . .
11.4 Combinatorics . . . . .
11.5 Bag-like operations . . .
11.6 Set-like operations . . .
11.7 Subsequence operations
6 Util.Pos
6.1 Maintenance notes . . . .
6.2 Positions in a source . . .
6.3 Overloaded projector . . .
6.3.1 Container intances
6.4 Relative positions . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
7
7
7
7
12 Data.NameTable
12.1 Maintenance notes . .
12.2 Data types . . . . . .
12.3 Creating a name table
12.4 Looking up by name .
12.5 Creating a name array
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
12
13
13
13
13
13
13 Data.Supply
13.1 Maintenance notes . .
13.2 Data types . . . . . .
13.3 Creating a supply . . .
13.4 Extracting values from
.
.
.
a
. . . .
. . . .
. . . .
supply
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
13
13
14 Debug.Array
14.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
14.2 Functions . . . . . . . . . . . . . . . . . . . . . . . .
13
13
13
15 Debug.IArray
15.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
15.2 Functions . . . . . . . . . . . . . . . . . . . . . . . .
14
14
14
.
.
.
.
.
.
.
.
.
.
.
.
April 3, 2015
16 Parser
16.1 Maintenance notes . . . . . . . .
16.2 Error messages . . . . . . . . . .
16.3 Results . . . . . . . . . . . . . . .
16.4 Analysers . . . . . . . . . . . . .
16.5 Elementary analysers . . . . . . .
16.6 Elementary analyser combinators
16.7 Analyser result modifiers . . . . .
16.8 More analyser combinators . . .
16.9 Lexers . . . . . . . . . . . . . . .
16.10Elementary lexers . . . . . . . . .
16.11Special combinators for lexers . .
16.12Frequently used lexers . . . . . .
16.13Parsing . . . . . . . . . . . . . .
16.14Elementary parsers . . . . . . . .
16.15Parser result modifiers . . . . . .
16.16Error reporting . . . . . . . . . .
16.17Instance declarations . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
14
14
14
14
14
15
15
15
16
16
16
17
17
17
17
17
17
17 Parser.Lexers
17.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
17.2 Frequently used lexers . . . . . . . . . . . . . . . . .
17
17
17
18 Parser.Checks
18.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
18.2 Easy lexer and parser sequencing . . . . . . . . . . .
19
19
19
19 Parser.Predicates
19.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
19.2 isNumber predicates . . . . . . . . . . . . . . . . . .
19
19
19
20 Text.Configs
20.1 Maintenance notes . . . . . . . . . . . . . .
20.2 Language tweaks . . . . . . . . . . . . . . .
20.3 Data types . . . . . . . . . . . . . . . . . .
20.4 Lexer . . . . . . . . . . . . . . . . . . . . .
20.5 Parser . . . . . . . . . . . . . . . . . . . . .
20.6 Showing . . . . . . . . . . . . . . . . . . . .
20.7 Reading . . . . . . . . . . . . . . . . . . . .
20.8 Accessing . . . . . . . . . . . . . . . . . . .
20.8.1 configPaths . . . . . . . . . . . . . .
20.8.2 Lookup functions . . . . . . . . . . .
20.9 Templates . . . . . . . . . . . . . . . . . . .
20.9.1 Simple Template Markup Language
20.9.2 Populating templates . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
19
19
19
20
20
21
21
21
21
21
22
22
22
21 Text.JSON
21.1 Maintenance notes .
21.2 Language tweaks . .
21.3 Basic data types . .
21.4 Escaping/descaping .
21.5 Construction . . . .
21.6 Lexer . . . . . . . .
21.7 Parser . . . . . . . .
21.8 Interrogation . . . .
21.9 Instances . . . . . .
21.9.1 Showing . . .
21.9.2 Interrogation
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
23
23
23
24
24
24
25
26
26
26
27
22 Text.CSV
22.1 Maintenance notes .
22.2 Basic data types . .
22.3 Parser . . . . . . . .
22.4 Interrogation . . . .
22.5 Instances . . . . . .
22.5.1 Showing . . .
22.5.2 Interrogation
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
27
27
27
27
27
27
23 Text.Markup
23.1 Maintenance notes . . . . . .
23.2 Making text safe for HTML .
23.3 Making text safe for LaTeX .
23.4 Converting LaTeX to HTML
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
27
28
28
April 3, 2015
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
24 Text.String
24.1 Maintenance notes . . . . . . . . .
24.2 Word wrapping . . . . . . . . . . .
24.3 Justification . . . . . . . . . . . . .
24.4 Tables with justified columns . . .
24.5 Fields . . . . . . . . . . . . . . . .
24.6 Whitespace . . . . . . . . . . . . .
24.7 Pattern matching and substitution
24.8 Names . . . . . . . . . . . . . . . .
24.9 Path catenation operators . . . . .
24.10Simple String Delimitation . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
29
29
30
30
30
30
31
31
31
31
25 Text.Showing
25.1 Maintenance notes .
25.2 Language tweaks . .
25.3 Adding Delimiters .
25.4 Controlling Precision
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
32
32
32
32
26 Logic.Kinds
26.1 Maintenance notes .
26.2 Data type . . . . . .
26.3 Unification . . . . .
26.4 Kind inference . . .
26.5 Instance declarations
26.5.1 Showing . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
32
32
32
32
32
33
33
27 Logic.Constants
27.1 Maintenance notes . . . . .
27.2 Data types . . . . . . . . .
27.3 Parsers . . . . . . . . . . . .
27.4 Collecting constants . . . .
27.5 Instance declarations . . . .
27.5.1 Comparing . . . . .
27.5.2 Positions . . . . . .
27.5.3 Showing . . . . . . .
27.5.4 Collecting constants
27.5.5 Kind inference . . .
27.5.6 DeepSeq . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
33
33
33
33
33
33
33
33
33
33
34
34
28 Logic.Variables
28.1 Maintenance notes . . . . .
28.2 Data type . . . . . . . . . .
28.3 Parsers . . . . . . . . . . . .
28.4 Collecting variables . . . . .
28.5 Grounding . . . . . . . . . .
28.6 Instance declarations . . . .
28.6.1 Comparing . . . . .
28.6.2 Positions . . . . . .
28.6.3 Showing . . . . . . .
28.6.4 Collecting variables .
28.6.5 Grounding . . . . .
28.6.6 Kind inference . . .
28.6.7 DeepSeq . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
34
34
34
34
34
34
34
34
34
34
34
34
34
34
29 Logic.Arguments
29.1 Maintenance notes . . . . .
29.2 Data type . . . . . . . . . .
29.3 Parsers . . . . . . . . . . . .
29.4 Instance declarations . . . .
29.4.1 Positions . . . . . .
29.4.2 Comparing . . . . .
29.4.3 Showing . . . . . . .
29.4.4 Collecting constants
29.4.5 Collecting variables .
29.4.6 Grounding . . . . .
29.4.7 Kind inference . . .
29.4.8 DeepSeq . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
35
35
35
35
35
35
35
35
35
35
35
35
36
30 Logic.Atoms
30.1 Maintenance notes . . . . .
30.2 Data type . . . . . . . . . .
30.3 Parsers . . . . . . . . . . . .
30.4 Collecting atoms . . . . . .
30.5 Instance declarations . . . .
30.5.1 Comparing . . . . .
30.5.2 Positions . . . . . .
30.5.3 Showing . . . . . . .
30.5.4 Collecting Atoms . .
30.5.5 Collecting constants
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
36
36
36
36
36
36
36
36
36
37
37
37
37
37
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
37
37
37
37
37
37
37
37
37
38
38
38
38
38
38
32 Logic.QuineMcClusky
32.1 Maintenance notes . . . . . .
32.2 Data types . . . . . . . . . .
32.3 Conversion from lists to trees
32.4 Conversion from trees to lists
32.5 Combining QMTrees . . . . .
32.6 Simplification . . . . . . . . .
32.7 Instance declarations . . . . .
32.7.1 DeepSeq . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
38
38
38
38
38
39
39
40
40
33 Graphics.Geometry
33.1 Maintenance notes . . .
33.2 Data types . . . . . . .
33.3 Geometric computations
33.4 Instance declarations . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
40
40
40
41
41
34 Graphics.EPS
34.1 Maintenance notes . . . . . . . .
34.2 Data types . . . . . . . . . . . .
34.3 Finalizing to EPS . . . . . . . . .
34.4 Drawing in BPS . . . . . . . . .
34.5 Merging BPS components . . . .
34.6 Drawing text . . . . . . . . . . .
34.6.1 Switching fonts efficiently
34.6.2 Font metrics . . . . . . .
34.6.3 Font tags . . . . . . . . .
34.6.4 Font strings . . . . . . . .
34.6.5 Font blocks . . . . . . . .
34.6.6 Text encoding . . . . . . .
34.7 Conveniences . . . . . . . . . . .
34.8 Instance declarations . . . . . . .
34.8.1 EPSDrawable . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
41
42
42
42
42
42
42
42
42
45
46
46
46
46
47
47
35 File.Lock
35.1 Maintenance notes . . .
35.2 Basic lock operations . .
35.3 Multiple file operations .
35.4 Guards . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
47
47
47
48
36 File.Versions
36.1 Maintenance notes . . . . . . . . .
36.2 Read the latest version . . . . . . .
36.3 Date of the latest version . . . . .
36.4 Write the next version . . . . . . .
36.5 Purge old versions . . . . . . . . .
36.6 Remove all versions . . . . . . . . .
36.7 Get all versions . . . . . . . . . . .
36.8 Read and write file bottlenecks . .
36.9 Creating and removing directories
36.10Private routines . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
48
48
48
48
48
48
48
49
49
49
49
April 3, 2015
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
37 CGI
37.1 Maintenance notes . . . . . . . . . .
37.2 Mime header . . . . . . . . . . . . .
37.3 Document type . . . . . . . . . . . .
37.4 Special character encoding . . . . . .
37.5 HTML elements (generic) . . . . . .
37.6 HTML elements (specific shortcuts)
37.7 Standards . . . . . . . . . . . . . . .
37.8 Bailing out . . . . . . . . . . . . . .
37.9 CGI inputs . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
49
50
50
50
50
50
50
51
51
51
38 Daytime
38.1 Maintenance notes .
38.2 Language tweaks . .
38.3 Data types . . . . .
38.4 Lexing . . . . . . . .
38.5 Parsing . . . . . . .
38.6 Instance declarations
38.6.1 Showing . . .
38.6.2 Arithmetic .
38.7 Weekday methods .
38.8 Daytime methods . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
52
52
52
52
52
53
54
54
54
54
54
39 HaskellLexer
39.1 Maintenance notes . . .
39.2 Language tweaks . . . .
39.3 Handling literate scripts
39.4 Lexing scripts . . . . . .
39.5 Handling the offside rule
39.6 Diagnostics . . . . . . .
39.7 Poor mans parsing . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
54
54
54
54
55
61
62
62
40 Playing Cards
40.1 Maintenance notes .
40.2 Data types . . . . .
40.3 Creating decks . . .
40.4 Instance declarations
40.5 Tests . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
63
64
64
64
64
64
. . . .
. . . .
. . . .
. . . .
cards
. . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
64
64
64
65
65
66
66
42 SendMail
42.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
42.2 Function . . . . . . . . . . . . . . . . . . . . . . . . .
66
66
66
43 (Experimental) Data.Graph
43.1 Maintenance notes . . . . .
43.2 Graph abstract data type .
43.3 Sparse graph type . . . . .
43.4 Example sparse graphs . . .
43.5 Graph Operations . . . . .
43.6 Reachability . . . . . . . . .
43.7 Cycles detection . . . . . .
43.8 Dense graph type . . . . . .
43.9 Imported Stuff . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
41 Poker
41.1 Maintenance notes . . .
41.2 Presorting and grouping
41.3 Categorisation of hands
41.4 Comparison of hands . .
41.5 Hands with more than 5
41.6 Tests . . . . . . . . . . .
44 (Experimental) MySQL C
44.1 Maintenance notes . . .
44.2 API Data types . . . . .
44.2.1 Basics . . . . . .
44.2.2 Connections . . .
44.2.3 Results . . . . .
44.2.4 Rows . . . . . . .
44.2.5 Fields . . . . . .
44.2.6 Options . . . . .
44.3 API Functions . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
66
66
66
66
67
67
67
67
67
67
API Binding
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
69
69
69
69
69
69
69
69
69
69
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
72
72
72
72
72
72
72
72
72
73
46 (Experimental) Database.Relational
46.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
46.2 Definitions and data types . . . . . . . . . . . . . . .
46.3 Relational algebra . . . . . . . . . . . . . . . . . . .
46.3.1 Projection of a tuple on a relation schema . .
46.3.2 Projection of a relation on a relation schema
46.3.3 Natural join . . . . . . . . . . . . . . . . . . .
46.3.4 Union . . . . . . . . . . . . . . . . . . . . . .
46.3.5 Difference . . . . . . . . . . . . . . . . . . . .
46.3.6 Selection . . . . . . . . . . . . . . . . . . . . .
46.3.7 Renaming . . . . . . . . . . . . . . . . . . . .
46.4 Datum operations . . . . . . . . . . . . . . . . . . .
73
73
73
73
73
73
73
74
74
74
74
74
47 (Deprecated) Data.BSTree
47.1 Maintenance notes . . . .
47.2 Language tweaks . . . . .
47.3 BSTree type . . . . . . . .
47.4 BSTree operations . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
References
81
Index
81
Introduction
This document lists and describes the libraries developed for and
common to the various systems I have developed in Haskell. These
include ENTRE (a toy functional language interpreter), Virgil (a
system for managing groups of students within a course), Deimos
(an implementation of Defeasible Logic), and Phobos (an implementation of Plausible Logic).
Each section in this document, except this introduction, is a complete listing of one module from the library.
Haskell code is presented in typewriter font. Some text in
typewriter font is not Haskell and is boxed to differentiate it from
Haskell. The source code for the Haskell modules have been written
in the literate style, and the following sections have been produced
directly from the Haskell+LATEX source code. The symbol $ appears is command examples to represent the command line prompt.
Milti-line commands are continued with the UNIX escape character,
\.
The SimpleLit tool has been used to separate interface and implementations into separate LATEX documents.
Please let me know of any defects or possible improvements that
you spot. Some modules are works-in-progress.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
74
74
74
74
75
48 (Deprecated) Data.HashTables
48.1 Maintenance notes . . . . . . .
48.2 Data types . . . . . . . . . . .
48.3 Creating a new hash table . . .
48.4 Updating an existing hash table
48.5 Looking up in a hash table . .
48.6 Dumping a hash table . . . . .
48.7 Test harness . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
76
76
76
76
77
77
77
77
49 (Deprecated) Data.Queue
49.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
49.2 Data type . . . . . . . . . . . . . . . . . . . . . . . .
49.3 Operations . . . . . . . . . . . . . . . . . . . . . . .
77
77
77
77
50 (Deprecated) Data.SparseSet
50.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
50.2 Data type . . . . . . . . . . . . . . . . . . . . . . . .
50.3 Operations . . . . . . . . . . . . . . . . . . . . . . .
78
78
78
78
51 (Deprecated) Data.Set
51.1 Maintenance notes .
51.2 Data type . . . . . .
51.3 Operations . . . . .
51.4 Instances . . . . . .
51.4.1 Ord . . . . .
51.4.2 Showing . . .
51.4.3 DeepSeq . . .
.
.
.
.
.
.
.
.
Installation
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
78
78
78
78
80
80
80
80
52 (Deprecated) DeepSeq
52.1 Maintenance notes . . .
52.2 Class Definition . . . . .
52.3 Infix operator . . . . . .
52.4 Instance Declarations . .
52.4.1 Simple instances
52.4.2 Tuple instances .
52.4.3 List instance . .
52.4.4 Maybe instance .
52.4.5 Either instance .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
80
80
80
80
80
80
80
80
80
80
$ make doc
.
.
.
.
.
.
.
.
.
53 (Deprecated) DeepSeq.BStree
53.1 Maintenance notes . . . . . . . . . . . . . . . . . . .
53.2 Instance declaration . . . . . . . . . . . . . . . . . .
80
80
80
$ make clean
54 (Deprecated) Logic.Qualification
54.1 Maintenance notes . . . . . . . .
54.2 Qualifiable class . . . . . . . . . .
54.3 Instance declarations . . . . . . .
54.3.1 Qualification . . . . . . .
81
81
81
81
81
April 3, 2015
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
$ make objects
To typeset the documentation, use
Util.Args
qualified
qualified
qualified
qualified
Data.List as L
Data.Sequence as S
Data.Foldable as F
Data.Map as M
3.1
Maintenance notes
3.2
Language tweaks
3.3
Data types
April 3, 2015
3.4
Empty options
3.5
Option detection
3.6
insertParam
and
3.7
Looking up options
4.1
Maintenance notes
4.2
cat = WEMessage {
cat,
Maybe Pos,
String
4.3
lookupQueue name options returns the list stored for the nameed
queue parameter in options or [] if it has not been properly specified.
3.8
Filename globbing
4.4
Data types
glob paths returns the really existing file names that match the
paths which may contain wildcards.
# if __GLASGOW_HASKELL__ < 705
-- legacy for hobbit
# else
glob :: [FilePath] -> IO [FilePath]
glob paths = do
(pathss, _) <- G.globDir (map G.compile paths) []
return $ L.nub $ concat pathss
# endif
Util.Errors
April 3, 2015
4.5
Returning
warning
successfully,
failing
or
4.6
4.6.1
Instances
Functor
4.6.2
Applicative
4.6.3
Monad
Making a WEResult a monad makes possible the silent accumulation messages as the computation proceeds, and stopping when its
failed.
instance Monad (WEResult cat) where
return = WEPass []
r >>= f = case r of
WEPass wems x -> case f x of
WEPass wems x -> WEPass (wems ++ wems) x
WEFail wems
-> WEFail (wems ++ wems)
WEFail wems
-> WEFail wems
Util.Open
5.1
5.4
Opening a URL
Util.Pos
6.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
Reviewed
6.2
2015-02-02.
2014-05-29:
2013-11-06.
2012-11-23:
2009-04-13:
Passed hlint.
Made all the -Walls go away.
Moved to ABR.Util from ABR.Parser.
Split from ABR.Parser.
Positions in a source
Maintenance notes
New 2015-04-02.
6.3
5.2
Positions get embedded in all kinds of parse tree types. Having one
overloaded function that projects out a Pos is useful. Make parse
tree types with postions in them an instance of HasPos .
System specifics
Overloaded projector
openTool is the system specific comand line tool for opening a URL
in the default browser. delimiter is the character(s) that should
delimit the URL. ampersand is the character(s) should replace any
ampersands in the URL.
openTool, delimiter, ampersand :: String
openTool =
#ifdef darwin_HOST_OS
"open"
#endif
#ifdef linux_BUILD_OS
"xdg-open"
#endif
#ifdef mingw32_BUILD_OS
"start"
#endif
delimiter =
#ifdef mingw32_BUILD_OS
""
#else
"\""
#endif
ampersand =
#ifdef mingw32_BUILD_OS
"^&"
#else
"&"
#endif
5.3
Tests
6.3.1
Container intances
6.4
Relative positions
Util.Time
testOpenURL :: IO ExitCode
testOpenURL = openURL "http://www.ict.griffith.edu.au/arock/itp/"
{-# LANGUAGE CPP #-}
April 3, 2015
module ABR.Util.Time (
LegacyTime,
C.UTCTime, LT.ZonedTime, LT.LocalTime,
utcToZonedTime, utcToLocalTime,
getCurrentUTCTime, getCurrentLocalTime,
getCurrentZonedTime,
TimeFormat, dateThenTime1, dateThenTime2,
formatTime, formatUTCTime,
currentTime, fileModTime,
LegacyTimes (getCurrentLegacyTime,
diffSec, diffMin, diffHour, diffDay,
formatLegacyTime)
) where
import qualified Data.Time.Clock as C
import qualified Data.Time.Format as F
import qualified Data.Time.LocalTime as LT
import qualified System.Directory as D
import qualified System.Locale as L
# if __GLASGOW_HASKELL__ < 705
-- legacy for hobbit
import qualified System.Time as ST
# else
# endif
7.1
Maintenance notes
7.2
Data types
7.3
Time conversions
7.5
Format strings
produces
Wed 27 Nov 2013 10:16:14 EST
Wed 27 Nov 2013 10:16:14
7.6
Formatting times
7.7
7.8
7.9
7.4
April 3, 2015
7.10
Instances
7.10.1
8.4
LegacyTimes
Parallel checks
Control.Check
Control.List
import ABR.Control.List
8.1
9.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
8.2
Data type
Maintenance notes
9.2
Backwards map
CheckPass passType
| CheckFail failType
8.3
Sequencing checks
ule.
April 3, 2015
10
Control.Map
10.1
Maintenance notes
10.2
lookupGuard
11
Data.List
merge :: (a -> a -> Bool) -> [a] -> [a] -> [a]
merge _ [] ys = ys
merge _ xs [] = xs
merge lt (x:xs) (y:ys)
| x lt y = x : merge lt xs (y:ys)
| otherwise = y : merge lt (x:xs) ys
split xs splits xs into two lists of the alternate elements of xs.
split :: [a] -> ([a],[a])
split xs = case xs of
[]
-> ([],[])
[x]
-> ([x],[])
(x1:x2:xs) -> let (xs1,xs2) = split xs
in (x1:xs1, x2:xs2)
cartProd produces the cartesian product of an arbitrary number
of lists. That is, cartProd [xs 1 , xs 2 , . . .] returns xs 1 xs 2 . . .
Note: Prelude.sequence can be used to do the same job.
cartProd :: [[a]] -> [[a]]
cartProd xs = case xs of
[]
-> [[]]
xs:xss -> [x : ys | x <- xs, ys <- cartProd xss]
module ABR.Data.List (
merge, msort, split, cartProd, interleave, separate,
fragments, fragments, dropEach, permutations,
permutations, combinations, subBag, bagElem,
powSet, powSet_ge1, powSet, powSet_ge1,
properSublists, pPlus, meet, disjoint, allUnique,
duplicates, snub, (+:), mnub, isSubset, findSubset,
noSuperSets, isSubSequence, notSubSequence, chop,
chops, subsSuffix, odiff, osect, ounion,
sortByLength, trimN, trim2, replace1, replaceAll
) where
11.1
Maintenance notes
11.2
Language tweaks
11.3
Sorting
11.4
Combinatorics
April 3, 2015
:: Int
_ [] =
0 _ =
k xs =
10
11.6
Set-like operations
11.5
Bag-like operations
infixl 5 +:
(+:) :: Ord a => [a] -> a -> [a]
xs +: x = snub (x : xs)
mnub xs ys merges lists xs and ys which must be in strictly ascending order. Any elements that occur in xs and ys occur only once in
the result.
mnub :: Ord a => [a] -> [a] -> [a]
mnub xs ys = case xs of
[]
-> ys
x : xs -> case ys of
[]
-> xs
y : ys | x < y
-> x : mnub xs ys
| x == y
-> x : mnub xs ys
| otherwise -> y : mnub xs ys
isSubset xs ys returns True iff xs ys. Precondition: xs and ys
are in strictly ascending order.
isSubset
isSubset
isSubset
isSubset
Bool
True
False
isSubset xs ys
False
isSubset (x:xs) ys
April 3, 2015
11
x
x
x
y
chops bs xs returns the sublists in xs that are separated by sequences equal to bs.
:
:
:
:
xs
ounion xs (y:ys)
ounion xs ys
ounion (x:xs) ys
11.7
Subsequence operations
April 3, 2015
12
Data.NameTable
Module ABR.Data.NameTable implements structures for the efficient accumulation of names, assigning unique, sequential integers
to each name and mapping between them.
12
module ABR.Data.NameTable (
NameTable, newNameTable, insertName, lookupName,
NameArray, makeNameArray
) where
13
Data.Supply
Module ABR.Data.Supply implements a name supply using a mutable variable in the IO monad.
import Data.Array.IArray
import Data.Array.IO
import qualified Data.Map as M
module ABR.Data.Supply (
Supply, newSupply, supplyNext, peekNext
) where
import ABR.Data.Supply
import Data.IORef
12.1
Maintenance notes
Reviewed 2015-02-02.
Reviewed 2014-06-03:
Reviewed 2013-11-21:
for IO functions.
Reviewed 2012-11-24:
Passed hlint.
Made all the -Walls go away.
Switch from hashtables to maps. Less need
Moved into ABR.Data.
13.1
Maintenance notes
13.2
Data types
12.2
Data types
type Supply a =
IORef a
12.3
13.3
Creating a supply
13.4
14
Debug.Array
12.4
Looking up by name
12.5
April 3, 2015
14.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
14.2
Functions
13
16
Parser
15
Debug.IArray
15.1
Maintenance notes
15.2
Functions
April 3, 2015
16.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
16.2
Error messages
16.3
Results
16.4
Analysers
16.5
Elementary analysers
This is the simplest analyser. succeedA v succeeds with a predetermined value v and does not consume any input.
succeedA :: b -> Analyser a b
succeedA v xs = OK (v, xs)
14
16.6
-> a2 xs
-> Error pos msg
-> OK stuff
( <&> ) ::
Analyser a b -> Analyser a c -> Analyser a (b,c)
( <&> ) a1 a2 xs
= case a1 xs of
Fail pos1 msg1 -> Fail pos1 msg1
Error pos1 msg1 -> Error pos1 msg1
OK (v1,ys)
-> case a2 ys of
Fail pos2 msg2 -> Fail pos2 msg2
Error pos2 msg2 -> Error pos2 msg2
OK (v2,zs)
-> OK ((v1,v2),zs)
16.8
April 3, 2015
16.7
some a changes analyser a which recognizes one thing into an analyser that recognizes a sequence of one or more things, returned in
a list. many a changes analyser a which recognizes one thing into
an analyser that recognizes a sequence of zero or more things, returned in a list. optional a changes analyser a which recognizes
one thing into an analyser that recognizes either zero or one things.
An empty or singleton list of things is returned.
15
dataSatisfies ::
Analyser a b -> (b -> Bool) -> Msg -> Analyser a b
dataSatisfies _ _ _ []
= Fail (-1,-1) "end of input"
dataSatisfies a test msg ((x,p):xps)
= case a ((x,p):xps) of
OK (dat,stuff) ->
if test dat then OK (dat, stuff)
else Fail p msg
Fail pos msg ->
Fail pos msg
Error pos msg ->
Error pos msg
total a forces analyser a to fail if it cant consume all the inputs.
total :: Analyser a b ->
total a xs
= case a xs of
Error pos msg
Fail pos msg
OK (v,[])
OK (_,(_,pos):_)
Analyser a b
->
->
->
->
16.9
Lexers
16.10
Elementary lexers
16.11
April 3, 2015
16
16.12
16.13
Parsing
16.14
Elementary parsers
tagP tag creates a parser that succeeds if the first lexeme has the
supplied tag. On failure, the message returned is "tag expected.".
tagP
tagP
tagP
|
16.16
Error reporting
16.17
Instance declarations
17
Parser.Lexers
literalP tag lexeme creates a parser that succeeds if the first tag
and lexeme match the supplied tag and lexeme. On failure, the
message returned is "tag "lexeme" expected.".
17.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
17.2
16.15
April 3, 2015
17
fixed
cardinal
.
cardinal
newline
\n
fixedL :: Lexer
fixedL =
cardinalL
<&&> soft (optional (
literalL .
<&&> soft (optional cardinalL)
))
%> "fixed"
\f
float
return
fixed
\r
whitespaceL :: Lexer
whitespaceL = some (satisfyL isSpace "") &%> " "
cardinal
+
E
-
floatL :: Lexer
floatL =
fixedL
<&&> soft (optional (
(literalL e <|> literalL E)
<&&> soft (optional (
literalL - <|> literalL +
))
<&&> nofail "exponent expected." cardinalL
))
%> "float"
signedCardinalL recognizes a signed whole number.
"
signedCardinal
cardinal
-
signedCardinalL :: Lexer
signedCardinalL =
soft (optional (literalL -)) <&&> cardinalL
%> "signedCardinal"
""
stringL :: Lexer
stringL =
literalL "
<&&> (many (
tokenL "\"\""
<|> satisfyL (/= ") "") &%> "")
<&&> literalL "
%> "string"
cardinalL recognizes a cardinal number, a sequence of decimal
digits.
cardinal ::= {$digit$}+.
cardinal
digit
signedFixedL :: Lexer
signedFixedL =
soft (optional (literalL -)) <&&> fixedL
%> "signedFixed"
signedFloat ::= ["-"] float.
signedFloat
float
cardinalL :: Lexer
cardinalL = some (satisfyL isDigit "digit") &%> "cardinal"
fixedL recognizes an unsigned fractional number with no exponent.
fixed ::= cardinal ["." [cardinal]].
April 3, 2015
signedFloatL :: Lexer
signedFloatL =
soft (optional (literalL -)) <&&> floatL
%> "signedFloat"
18
18
Parser.Checks
18.1
Maintenance notes
18.2
19.2
isCardinal ,
Parser.Predicates
isFixed ,
isFloat ,
isSignedCardinal ,
20
Text.Configs
20.1
ABR.Parser
ABR.Parser.Lexers
ABR.Text.String
ABR.Text.Showing
Maintenance notes
20.2
19
isNumber predicates
Language tweaks
20.3
Data types
import ABR.Control.Check
import ABR.Parser.Checks
import ABR.Parser.Lexers
19.1
Maintenance notes
April 3, 2015
data Config =
CFlag String
| CParam String String
| CSet String Configs
| CList String [Configs]
deriving (Eq, Ord)
19
20.4
Lexer
configsL
comment
name
comment ::=
"#" {$anything not \\n$} ("\\n" | $end of file$);
level="lexical".
string
=
{
comment
#
anything not \n
\n
end of file
commentL :: Lexer
commentL =
literalL #
<&&> (many (satisfyL (/= \n) "") &%> "")
<&&> (optional (literalL \n) &%> "")
%> " "
Names in configuration files may contain letters, digits, plus and
minus signs, underscores, periods, bangs and slashes. Note that a
number can lex as a name, as could many file paths. Names are case
sensitive.
name ::= {$letter$ | $digit$ |
"+" | "-" | "_" | "." | "!" | "/"}+;
level="lexical".
]
,
whitespace
configsL :: Lexer
configsL = dropWhite $ nofail $ total $ listL [
commentL, nameL, stringL,
tokenL "=" %> "symbol", tokenL "{" %> "symbol",
tokenL "}" %> "symbol", tokenL "[" %> "symbol",
tokenL "]" %> "symbol", tokenL "," %> "symbol",
whitespaceL
]
20.5
name
letter
Parser
digit
+
-
value
_
name
string
nameL :: Lexer
nameL = some (satisfyL nameChar "") &%> "name"
where
nameChar :: Char -> Bool
nameChar c =
isAlpha c || isDigit c || c elem "+-_.!/"
Strings are delimited by double quotes and may extend across many
lines. Use two double quotes for one, a
` la Pascal.
configs
config
string
"
"
""
anything not "
configs
April 3, 2015
20
"[" "]"
| "[" configs {"," configs}+ "]"
| "[" configs "]";
level="grammar".
configList ::=
configList
[
configs
configs
configs
20.7
]
Reading
20.8
20.8.1
Accessing
configPaths
20.8.2
Lookup functions
config ::=
config
name
value
name
configSet
name
configList
name
20.6
Showing
April 3, 2015
21
| otherwise ->
c : updateConfig n c cs
c@(CParam n _) : cs
| n == n ->
c : cs
| otherwise ->
c : updateConfig n c cs
c@(CSet n cs) : cs
| n == n ->
c : cs
| (n ++ ".") isPrefixOf n ->
CSet n (updateConfig (drop (length n + 1) n) c
cs) : cs
| otherwise ->
c : updateConfig n c cs
c@(CList n css) : cs
| n == n ->
c : cs
| (n ++ "!") isPrefixOf n ->
let (i,n) =
span isDigit (drop (length n + 1) n)
(css,cs:css) = splitAt (read i) css
in CList n (css ++ updateConfig (tail n) c cs
: css) : cs
| otherwise ->
c : updateConfig n c cs
lookupParam n cs tries to find the named parameter n in cs, returning Just the first value or Nothing. (Note elem is all that is
required to test for a flag.) n is a configPath.
lookupParam :: String -> Configs -> Maybe String
lookupParam n cs = case lookupConfig n cs of
Nothing
-> Nothing
Just (CParam _ v) -> Just v
_ -> undefined "lookupParam"
getParam n cs tries to find the named parameter. It is an error if
the parameter can not be found. n is a configPath.
getParam:: String -> Configs -> String
getParam name cs =
let mp = lookupParam name cs
in fromMaybe (error $ "Missing config: " ++ name) mp
20.9
Templates
Configs are a structured data type like XML and can be used to
populate a template. The power of templates in part comes from
being able to handle variations in the data that they might get
populated with.
20.9.1
April 3, 2015
20.9.2
Populating templates
popTemplate configs template returns the text of the template populated with the data from the configs. NOT TESTED
data Mode = Quiet | Print | Reprint
popTemplate :: Configs -> String -> String
popTemplate configs = pt [(configs,Print)]
where
pt :: [(Configs,Mode)] -> String -> String
-- every #end# pops a context. in each tuple is the
-- current Configs and whether to output
pt [] "" = ""
pt [_] "" = ""
pt (_:_:_) "" = "popTemplate: not enough #end#s."
pt [] _ = error "popTemplate: too many #end#s."
pt contexts@((g,m):gvs) template = case template of
#:#:cs -> case m of
Quiet -> pt contexts cs
_
-> # : pt contexts cs
#:e:n:d:#:cs -> case m of
Reprint -> ""
_
-> pt gvs cs
#:i:f:d:e:f:#:cs ->
case span (/= #) cs of
([],_) ->
error "popTemplate: empty path (1)"
(_,[]) ->
error "popTemplate: non-terminated path (1)"
(path,#:cs) -> case m of
Quiet -> pt ((g,Quiet):contexts) cs
_
-> case lookupConfig path g of
Nothing -> pt ((g,Quiet):contexts) cs
Just _ -> pt ((g,Print):contexts) cs
_ -> undefined "pt 1"
#:i:f:u:n:d:e:f:#:cs ->
case span (/= #) cs of
([],_) ->
error "popTemplate: empty path (2)"
(_,[]) ->
error "popTemplate: non-terminated path (2)"
(path,#:cs) -> case m of
Quiet -> pt ((g,Quiet):contexts) cs
_
-> case lookupConfig path g of
Nothing -> pt ((g,Print):contexts) cs
Just _ -> pt ((g,Quiet):contexts) cs
_ -> undefined "pt 2"
#:w:i:t:h:#:cs ->
case span (/= #) cs of
([],_) ->
error "popTemplate: empty path (3)"
(_,[]) ->
error "popTemplate: non-terminated path (3)"
(path,#:cs) -> case m of
Quiet -> pt ((g,Quiet):contexts) cs
_
-> case lookupConfig path g of
Nothing -> "_UNDEFINED_SET_" ++
22
pt ((g,Quiet):contexts) cs
Just (CSet _ g) ->
pt ((g,Print):contexts) cs
Just _ -> "_NOT_A_SET_" ++
pt ((g,Quiet):contexts) cs
_ -> undefined "pt 3"
#:f:o:r:e:a:c:h:#:cs ->
case span (/= #) cs of
([],_) ->
error "popTemplate: empty path (4)"
(_,[]) ->
error "popTemplate: non-terminated path (4)"
(path,#:cs) -> case m of
Quiet -> pt ((g,Quiet):contexts) cs
_
-> case lookupConfig path g of
Nothing ->
"_UNDEFINED_LIST_" ++
pt ((g,Quiet):contexts) cs
Just (CList _ g) -> case g of
[] -> pt (([],Quiet):contexts) cs
es -> concat [pt
((e,Reprint):contexts) cs |
e <- init es] ++
pt ((last es,Print):contexts) cs
Just _ ->
"_NOT_A_List_" ++
pt ((g,Quiet):contexts) cs
_ -> undefined "pt 4"
#:cs ->
case span (/= #) cs of
([],_) ->
error "popTemplate: empty path (5)"
(_,[]) ->
error "popTemplate: non-terminated path (5)"
(path,#:cs) -> case m of
Quiet -> pt contexts cs
_
-> case lookupConfig path g of
Nothing ->
"_UNDEFINED_" ++ pt contexts cs
Just (CFlag _) ->
"_DEFINED_" ++ pt contexts cs
Just (CParam _ v) ->
unString v ++ pt contexts cs
Just (CSet _ _) ->
"_SET_" ++ pt contexts cs
Just (CList _ _) ->
"_LIST_" ++ pt contexts cs
_ -> undefined "pt 5"
c:cs -> case m of
Quiet -> pt contexts cs
_
-> c : pt contexts cs
_ -> undefined "pt 6"
21
Text.JSON
ABR.Util.Pos
ABR.Text.Showing
ABR.Parser
ABR.Parser.Lexers hiding (stringL)
April 3, 2015
21.1
Maintenance notes
21.2
Language tweaks
21.3
23
21.4
Escaping/descaping
21.6
Lexer
digit19L :: Lexer
digit19L = satisfyL (\c -> 1 <= c && c <= 9) "digit19"
digit ::= "0" | digit19
; level="lexical".
digit
0
digit19
digitL :: Lexer
digitL =
(
literalL 0
<|> digit19L
)
%> "digit"
hexDigit ::=
digit | "a" | $...$ | "f" | "A" | $...$ | "F"
; level="lexical".
hexDigit
digit
a
...
f
A
...
21.5
Construction
April 3, 2015
hexDigitL :: Lexer
hexDigitL =
(
digitL
<|> satisfyL (\c -> a <= c && c <= f ||
A <= c && c <= F) ""
)
%> "hexDigit"
string ::=
"\""
{<$any character$ ! "\""| "\\"> | escapeSequence}
"\""
; level="lexical".
string
"
"
any character
not
"
\
escapeSequence
stringL :: Lexer
stringL =
literalL \"
<&&> (many (
satisfyL (notElem "\"\\") ""
<|> escapeSequenceL
) &%> "")
<&&> nofail (literalL \")
%> "string"
24
separator
,
:
{
}
escapeSequence
\
"
\
/
b
f
n
r
t
hexDigit
hexDigit
hexDigit
hexDigit
escapeSequenceL :: Lexer
escapeSequenceL =
literalL \\
<&&> (
literalL \"
<|> literalL \\
<|> literalL /
<|> literalL b
<|> literalL f
<|> literalL n
<|> literalL r
<|> literalL t
<|> hexDigitL <&&> hexDigitL <&&> hexDigitL <&&>
hexDigitL
)
%> "excapeSequence"
number ::= ["-"] ("0" | digit19 {digit}) ["." {digit}] \
[("e" | "E") ($epsilon$ | "+" | "-") {digit}+]
; level="lexical".
separatorL :: Lexer
separatorL =
(
literalL ,
<|> literalL :
<|> literalL {
<|> literalL }
<|> literalL [
<|> literalL ]
)
%> "separator"
keyword ::= "true" | "false" | "null"
; level="lexical".
keyword
true
false
null
keywordL :: Lexer
keywordL =
(
tokenL "true"
<|> tokenL "false"
<|> tokenL "null"
)
%> "keyword"
lexerL lexes a JSON source.
number
0
-
digit19
digit
e
E
digit
digit
lexer
whitespace
separator
numberL :: Lexer
numberL =
soft (optional (literalL -))
<&&> (
literalL 0
<|> digit19L <&&> (many digitL &%> "")
)
<&&> soft (optional (
literalL .
<&&> (many digitL &%> "")
))
<&&> soft (optional (
(literalL e <|> literalL E)
<&&> soft (optional (literalL + <|>
literalL -))
<&&> soft (some digitL)
))
%> "number"
string
number
keyword
lexerL :: Lexer
lexerL = dropWhite $ nofail $ total $ listL [whitespaceL,
separatorL, stringL, numberL, keywordL]
21.7
Parser
April 3, 2015
25
value
<&> optional (
valueP
<&> many (
literalP "separator" ","
&> nofail "value expected" valueP
)
@> cons
)
<& nofail (literalP "separator" "]")
@> (\((_,_,p), vss) -> JArray {
jArray = let vs = concat vss
in A.listArray (0, length vs - 1) vs,
jPos = p
})
string
number
object
array
true
false
null
21.8
Interrogation
JQProps The value is an object, return all of the the properties as a list of (name, value) pairs.
object
{
property
,
property
property
string
value
array
]
value
,
April 3, 2015
value
21.9.1
Instances
Showing
21.9
26
showString "{\n" .
showWithSep ",\n"
(map (uncurry JProperty) (M.toList obj)) .
showString "\n}"
JArray arr _ ->
showString "[\n" .
showWithSep ",\n" (A.elems arr) .
showString "\n]"
JTrue
_ ->
showString "true"
JFalse
_ ->
showString "false"
JNull
_ ->
showString "null"
22.1
Maintenance notes
22.2
21.9.2
Interrogation
22.4
Interrogation
22.5
Instances
22.3
Parser
22.5.1
Showing
22
Text.CSV
April 3, 2015
22.5.2
23
Interrogation
Text.Markup
23.1
Maintenance notes
23.2
27
23.3
23.4
April 3, 2015
r : rs ->
let (vs, rs) = break (== r) rs
in "<tt>" ++ makeHTMLSafe vs ++
"</tt>" ++ t2h ends (drop 1 rs)
_
-> t2h ends rest
-- MORE CASES GO HERE
c : cs ->
c : t2h ends cs
[] ->
concat ends
t2h newEnd ends cs converts LATEX string cs to HTML. ends is a
list of element closes awaiting the next }. We are currently in text
mode. newEnd is a new closing tag to add to the innermost ending.
t2h :: String -> [String]
t2h newEnd ends cs = case
[]
-> t2h [newEnd]
e : es -> t2h ((newEnd
28
"eta"
"theta"
"iota"
"kappa"
"lambda"
"mu"
"nu"
"xi"
"omicron"
"pi"
"rho"
"sigma"
"tau"
"upsilon"
"phi"
"chi"
"psi"
"omega"
"Alpha"
"Beta"
"Gamma"
"Delta"
"Epsilon"
"Zeta"
"Eta"
"Theta"
"Iota"
"Kappa"
"Lambda"
"Mu"
"Nu"
"Xi"
"Omicron"
"Pi"
"Rho"
"Sigma"
"Tau"
"Upsilon"
"Phi"
April 3, 2015
getCommand cs splits a string into the first run of letters and the
rest. A space at the end of the run of letters is discarded (as per
LATEX).
getCommand :: String -> (String, String)
getCommand cs = case cs of
"" ->
("", "")
: cs ->
("", cs)
c : cs
| isAlpha c ->
let (command, rest) = getCommand cs
in (c : command, rest)
| otherwise ->
("", c : cs)
24
Text.String
24.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
24.2
Word wrapping
29
24.3
Justification
makeTableL c cols makes a table from cols using all left justification, with c used to pad columns and separate columns.
makeTableL :: Char -> [[String]] -> String
makeTableL c cols = makeTable (repeat (lJustify c)) $
spaceColumns [c] cols
makeTableMR js rows makes a table from elements that are themselves multi-rowed. js is a list of justifiers for each column (as in
makeTable. rows is a list of rows, where each row is a list of columns.
makeTableMR :: [Int -> String -> String] ->
[[[String]]] -> String
makeTableMR js =
let padcs cols =
let h = maximum $ map length cols
pad col = col ++ replicate (h - length col) ""
in map pad cols
in makeTable js . map concat . transpose . map padcs
24.4
April 3, 2015
24.5
Fields
These are functions for breaking a string into a list of fields and
converting a list of fields into a string. The fields are delimited with
a nominated special character. To permit the special character to
appear in a field it is preceded by a nominated escape character. To
permit the escape character to appear in a string, it is preceded by
itself.
fields d e cs breaks string cs into a list of strings at each delimit
character d, removing escape characters e where appropriate. If the
ecsaping is not required use ABR.Data.List.chop instead.
fields :: Char -> Char -> String -> [String]
fields d e cs = case cs of
[] -> []
_ -> f [] [] cs
where
f css rs cs = case cs of
[] ->
reverse (reverse rs : css)
[c]
| c == d ->
reverse ([] : reverse rs : css)
| otherwise ->
reverse (reverse (c:rs) : css)
c:c:cs
| c == e && c == d ->
f css (d:rs) cs
| c == e && c == e ->
f css (e:rs) cs
| c == d ->
f (reverse rs : css) [] (c:cs)
| otherwise ->
f css (c:rs) (c:cs)
unfields d e css converts css into one string, with each field separated by the delimit character d, adding escape characters e as
needed. If the ecsaping is not required use Data.List.intersperse
instead.
unfields :: Char -> Char -> [String] -> String
unfields d e css = case css of
[]
-> []
[cs]
-> escape cs
cs:cs:css -> escape cs ++ [d]
++ unfields d e (cs:css)
where
escape :: String -> String
escape []
= []
escape (c:cs)
| c == d
= e : d : escape cs
| c == e
= e : e : escape cs
| otherwise = c : escape cs
24.6
Whitespace
30
24.8
Names
24.9
++/++ joins two paths with a single /. ++.++ joins two paths with
a single . The utility of these operators is that any extra /s or .s
at the join are removed.
infixl 6 ++/++, ++.++
24.7
April 3, 2015
24.10
25
Text.Showing
31
25.1
Maintenance notes
26.1
Reviewed
Reviewed
Reviewed
Reviewed
Reviewed 2013-11-24.
Reviewed 2012-11-23: Saved from the CDL project for RL/PL.
25.2
Language tweaks
25.3
Adding Delimiters
26.2
25.4
Controlling Precision
of
md x
md x
md x
26
Logic.Kinds
April 3, 2015
Data type
types yield tuple kinds ( KTuple ). There should never be less than
two elements in a tuple kind. A with variables in it has an unknown
kind ( KUnknown ).
data Kind =
Maintenance notes
KNamed
| KIntegral
| KString
| KTuple [Kind]
| KUnknown
deriving (Eq, Ord)
26.3
Unification
26.4
Kind inference
precondition:
32
26.5
Instance declarations
26.5.1
integer
Showing
27
uName
where
case k of
showChar *
showChar #
showChar $
showChar ( . showWithSep "," ks
. showChar )
-> showChar ?
Logic.Constants
string
27.4
Collecting constants
27.1
Maintenance notes
Data types
27.3
27.5
27.2
27.5.1
Comparing
=
=
=
=
n == n
i == i
s == s
False
27.5.2
Parsers
Instance declarations
Positions
April 3, 2015
27.5.3
Showing
27.5.4
Collecting constants
33
27.5.5
Kind inference
28.5
Grounding
27.5.6
DeepSeq
instance NFData
rnf c = case
CNamed
CIntegral
CString
28
Constant
c of
n p -> n
i p -> i
s p -> s
where
deepseq p deepseq ()
deepseq p deepseq ()
deepseq p deepseq ()
Logic.Variables
28.1
NullSub
| Variable :->- Constant
| Substitution :>-> Substitution
deriving (Eq, Ord, Show)
ABR.Util.Pos
ABR.Parser
ABR.Logic.Kinds
ABR.Logic.Constants
Maintenance notes
28.6
Instance declarations
28.6.1
28.2
Data type
28.3
Comparing
28.6.2
Positions
Parsers
28.6.3
Showing
28.6.4
Collecting variables
28.4
Collecting variables
28.6.5
Grounding
28.6.6
Kind inference
April 3, 2015
28.6.7
DeepSeq
34
29
Logic.Arguments
29.4
29.1
instance
Const
Var
Tuple
ABR.Util.Pos
ABR.Parser
ABR.Text.Showing
ABR.Logic.Kinds
ABR.Logic.Constants
ABR.Logic.Variables
Comparing
Eq
c
v
as
Argument where
_ == Const c _ = c == c
_ == Var
v _ = v == v
_ == Tuple as _ = as == as
Maintenance notes
29.2
Positions
29.4.2
import Control.DeepSeq
import
import
import
import
import
import
29.4.1
Instance declarations
Data type
29.4.3
Showing
data Argument =
Const {
arConst :: Constant,
arPos
:: Pos
}
| Var {
arVar :: Variable,
arPos :: Pos
}
| Tuple {
arElems :: [Argument],
arPos
:: Pos
}
29.4.4
Parsers
argument ::=
constant
| variable
| "(" argument {"," argument}+ ")".
29.4.6
argument
constant
variable
(
argument
argument
April 3, 2015
29.4.5
Collecting variables
29.3
Collecting constants
Grounding
29.4.7
p
p
p
p
p
p
Kind inference
35
29.4.8
DeepSeq
specialAtom ::= argument ("<" | "<=" | "==") argument.
specialAtom
argument
<
argument
<=
==
30
Logic.Atoms
atom
atomName
module ABR.Logic.Atoms (
Atom(..), atomNameP, atomP, HasAtoms(..)
) where
argList
string
30.1
specialAtom
ABR.Util.Pos
ABR.Parser
ABR.Text.Showing
ABR.Logic.Kinds
ABR.Logic.Constants
ABR.Logic.Variables
ABR.Logic.Arguments
Maintenance notes
30.2
Data type
30.3
30.4
Collecting atoms
Parsers
atomName
lName
30.5
uName
30.5.1
argList
argument
)
,
argument
.
argListP recognises argument lists.
argListP :: Parser [Argument]
argListP =
literalP "symbol" "("
&> argumentP
<&> many (literalP "symbol" "," &> argumentP)
<& nofail (literalP "symbol" ")")
@> cons
.
April 3, 2015
Comparing
Instance declarations
30.5.2
Positions
30.5.3
Showing
36
literal
[] -> showString n
as -> showString n . showChar ( .
showWithSep "," as . showChar )
30.5.4
atom
Collecting Atoms
literal
literal
30.5.7
31.4
30.5.5
Collecting constants
30.5.6
Collecting variables
Grounding
30.5.8
DeepSeq
31
Logic.Literals
Negation
module ABR.Logic.Literals (
Literal(..), pLiteralP, Negatable(..),
Complementable(..)
) where
import Control.DeepSeq
import
import
import
import
import
31.1
ABR.Util.Pos
ABR.Parser
ABR.Logic.Constants
ABR.Logic.Variables
ABR.Logic.Atoms
Maintenance notes
31.2
Data type
31.3
Atom,
Pos
Atom,
Pos
Parser
April 3, 2015
31.5
31.5.1
Instance declarations
Comparing
31.5.2
Positions
31.5.3
Showing
37
31.5.4
32.2
Negation
Data types
This is a label with which to tag a term, and those derived from it.
The original terms will be labelled 0, 1, . . .
31.5.5
Collecting Atoms
31.5.6
Collecting constants
31.5.7
where
of
a vs
a vs
Grounding
31.5.9
a) p
a) p
a) p
a) p
DeepSeq
32
Logic.QuineMcClusky
ABR.Logic.QuineMcClusky
implements the QuineModule
McClusky algorithm for simplifying boolean expressions as
described in Rosen[3].
module ABR.Logic.QuineMcClusky (
QMBit(..), qmSimplify
) where
import
import
import
import
import
import
import
Control.DeepSeq
Data.List
Data.Maybe
Data.Array.IArray
Data.Array.MArray
Data.Array.IO
System.IO
import ABR.Data.List
32.1
Maintenance notes
April 3, 2015
data QMTree =
Example QMTrees:
Collecting variables
31.5.8
where
of
a cs
a cs
0:
0:
1:
0:
1:
2:
[]
[0]
[1]
[00]
[-0]
[10]
N
Y [0]
ZDO (Y [0]) N (Y [1])
ZDO
(ZDO (Y [0])
(ZDO (Y [1])
(ZDO (Y [2])
0: [00]
ZDO
1: [10]
(ZDO (Y [0])
N
(ZDO (Y [1])
A term is a list of bits, tagged by the list
original terms from which it is derived.
N N)
N N)
N N)
N N)
N N)
of labels assigned to the
32.3
32.4
38
32.5
Combining QMTrees
tCombine t t0 returns the bit strings that result from successful combinations of the bit strings in t and t0 . All the bit strings in t and
t0 have the same number of 1s and that number for t differs from
that of t0 by 1.
tCombine :: QMTree -> QMTree -> QMTree
tCombine t t = case t of
ZDO z d o -> case t of
ZDO z d o -> ZDO
(tCombine z z)
(tUnion (tCombine d d)
(tUnion (tSect z o) (tSect o z)))
(tCombine o o)
_
-> N
_
-> N
tSect t t0 returns the bit strings that occur in t and t0 .
tSect :: QMTree -> QMTree -> QMTree
tSect t t = case t of
N
-> N
Y l
-> case t of
Y l
-> Y (mnub l l)
N
-> N
ZDO _ _ _ -> error
"ABR.QuineMcClusky.tSect: mismatched length"
ZDO z d o -> case t of
ZDO z d o -> case (tSect z z,
tSect d d,
tSect o o) of
(N,
N,
N)
-> N
(z, d, o) -> ZDO z d o
_
-> N
tUnion t t0 returns the bit strings that occur in either t or t0 .
tUnion :: QMTree -> QMTree -> QMTree
tUnion t t = case t of
N
-> t
Y l
-> case t of
N
-> t
Y l
-> Y (mnub l l)
ZDO _ _ _ -> error
"ABR.QuineMcClusky.tUnion: mismatched length"
ZDO z d o -> case t of
N
-> t
ZDO z d o -> ZDO (tUnion z z)
(tUnion d d)
(tUnion o o)
Y _
-> error
"ABR.QuineMcClusky.tUnion: mismatched length"
diff t t0 returns the bit strings that occur in t but not in t0 .
diff :: QMTree -> QMTree -> QMTree
diff t t = case t of
N
-> N
Y _
-> case t of
N
-> t
Y _
-> N
ZDO _ _ _ -> error
"ABR.QuineMcClusky.diff: mismatched length"
ZDO z d o -> case t of
N
-> t
ZDO z d o -> case (diff z z,
diff d d,
diff o o) of
(N,
N,
N)
-> N
(z, d, o) -> ZDO z d o
Y _
-> error
"ABR.QuineMcClusky.tUnion: mismatched length"
April 3, 2015
unusedOne t t0 returns the bit strings that occur in t but not used
in t0 . If it were used in t0 then there would be a bit string in t0 that
was exactly the same but for one one changed to a dash.
unusedOne :: QMTree -> QMTree -> QMTree
unusedOne t t = case t of
N
-> N
Y _
-> t
ZDO z d o -> case t of
N
-> t
ZDO z d o -> case (unusedOne z z,
unusedOne d d,
diff (unusedOne o o)
(tSect o d)) of
(N,
N,
N)
-> N
(z, d, o) -> ZDO z d o
Y _
-> error
"ABR.QuineMcClusky.unusedOne: mismatched length"
unusedZero t t0 returns the bit strings that occur in t but not used
in t0 . If it were used in t0 then there would be a bit string in t0 that
was exactly the same but for one zero changed to a dash.
unusedZero :: QMTree -> QMTree -> QMTree
unusedZero t t = case t of
N
-> N
Y _
-> t
ZDO z d o -> case t of
N
-> t
ZDO z d o -> case (diff (unusedZero z z)
(tSect z d),
unusedZero d d,
unusedZero o o) of
(N,
N,
N)
-> N
(z, d, o) -> ZDO z d o
Y _
-> error
"ABR.QuineMcClusky.unusedZero: mismatched length"
32.6
Simplification
39
April 3, 2015
32.7
32.7.1
Instance declarations
DeepSeq
33
Graphics.Geometry
33.1
Maintenance notes
33.2
Data types
40
(x,y)
b
a
Ax + by + C = 0
33.3
Geometric computations
Figure 2: An ellipse.
iBox b converts the coordinates of box b to Ints.
iBox :: Box a -> Box Int
iBox (l,b,r,t) = (iGeo l, iGeo b, iGeo r, iGeo t)
insetBox d (l, b, r, t) reduces box (l, b, r, t) all around by distance
d. It is assumed that 2d r l and 2d t b, that is that the
original box was big enough to do this.
insetBox :: a -> Box a -> Box a
insetBox d (l,b,r,t) = (l + d, b + d, r - d, t - d)
segToLine ((x1 , y1 ), (x2 , y2 )) computes (A, B, C) for segment
((x1 , y1 ), (x2 , y2 )). Working:
A = y2 y1 , B = x2 x1 , C = (Ax1 + By1 )
segToLine :: LineSeg a -> Line a
segToLine ((x1,y1),(x2,y2)) =
let a = y2 - y1
b = x1 - x2
in (a, b, -(a * x1 + b * y1))
insetSeg d ((x1 , y1 ), (x2 , y2 )) clips a distance d from both ends of
the line segment. It is assumed that the line segment is long enough
to do this.
insetSeg :: a -> LineSeg a -> LineSeg a
segToLine d ((x1,y1),(x2,y2)) = undefined
33.4
Instance declarations
April 3, 2015
placeAroundOval n (l,b,r,t) p =
let p = p * pi / 180.0
g = 2.0 * pi / fromIntegral n
a = (r - l) / 2.0
b = (t - b) / 2.0
in [(l + a + a * cos t, b + b + b * sin t)
| i <- [0..n-1], let t = p - fromIntegral i * g]
instance GeoNum Int where
iGeo = id
instance GeoNum Integer where
iGeo = fromIntegral
instance GeoNum Rational where
iGeo = round
34
Graphics.EPS
41
import ABR.Util.Args
import ABR.Graphics.Geometry
34.1
Maintenance notes
Reviewed
Reviewed
Reviewed
Reviewed
34.2
Data types
setUpFonts :: PS
setUpFonts = [
"/symbol10 { fs10 setfont } def",
"/times10 { ftr10 setfont } def",
"/times10ital { fti10 setfont } def",
"/helv10 { fh10 setfont } def",
"/helv10obl { fho10 setfont } def",
"/helv10bld { fhb10 setfont } def",
"/helv10bldobl { fhbo10 setfont } def",
"/ftr10 /Times-Roman findfont 10 scalefont def",
"/fti10 /Times-Italic findfont 10 scalefont def",
"/fh10 /Helvetica findfont 10 scalefont def",
"/fho10 /Helvetica-Oblique findfont 10 scalefont def",
"/fhb10 /Helvetica-Bold findfont 10 scalefont def",
"/fhbo10 /Helvetica-BoldOblique findfont 10 scalefont\
\ def",
"/fs10 /Symbol findfont 10 scalefont def"
]
34.6.2
type PS = [String]
times10Width
times10Width
->
!
->
"
->
#
->
$
->
%
->
&
->
\
->
(
->
)
->
*
->
+
->
,
->
-
->
.
->
/
->
0
->
1
->
2
->
3
->
4
->
5
->
6
->
7
->
8
->
9
->
:
->
;
->
<
->
=
->
>
->
?
->
@
->
A
->
B
->
C
->
D
->
E
->
F
->
G
->
H
->
I
->
J
->
K
->
L
->
M
->
N
->
O
->
P
->
Q
->
R
->
S
->
T
->
34.3
Finalizing to EPS
34.4
Drawing in BPS
34.5
34.6
34.6.1
Drawing text
Switching fonts efficiently
April 3, 2015
Font metrics
42
U
V
W
X
Y
Z
[
\\
]
^
_
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
\170
\177
\186
_
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
7.21992
7.21992
9.43984
7.21992
7.21992
6.10977
3.32969
2.77969
3.32969
4.68984
5.0
3.32969
4.43894
5.0
4.43894
5.0
4.43894
3.32969
5.0
5.0
2.77969
2.77969
5.0
2.77969
7.77969
5.0
5.0
5.0
5.0
3.32969
3.88984
2.77969
5.0
5.0
7.21992
5.0
5.0
4.43894
4.8
2.0
4.8
5.40977
4.43984 -- open double quote
5.0 -- dash/minus
4.43984 -- close double quote
2.5
times10ItalWidth c returns the width of a character c in TimesItalic 10 point, in 72 dpi pixels. (not exhaustive)
times10ItalWidth :: Char -> Double
times10ItalWidth c = case c of
0
-> 5.0
1
-> 5.0
2
-> 5.0
3
-> 5.0
4
-> 5.0
5
-> 5.0
6
-> 5.0
7
-> 5.0
8
-> 5.0
9
-> 5.0
A
-> 6.10999
B
-> 6.10999
C
-> 6.67
D
-> 7.22
E
-> 6.10999
F
-> 6.10999
G
-> 7.22
H
-> 7.22
I
-> 3.32998
J
-> 4.43999
K
-> 6.67
L
-> 5.55999
M
-> 8.32998
N
-> 6.67
O
-> 7.22
P
-> 6.10999
Q
-> 7.22
R
-> 6.10999
April 3, 2015
S
T
U
V
W
X
Y
Z
_
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
_
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
5.0
5.55999
7.22
6.10999
8.32998
6.10999
5.55999
5.55999
5.0
5.0
5.0
4.43999
5.0
4.43999
2.77998
5.0
5.0
2.77998
2.77998
4.43999
2.77998
7.22
5.0
5.0
5.0
5.0
3.88999
3.88999
2.77998
5.0
4.43999
6.67
4.43999
4.43999
3.88999
2.5
43
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\\
]
^
_
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
\170
\177
\186
_
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
6.1084
7.77832
7.22168
2.77832
5.0
6.66992
5.56152
8.33008
7.22168
7.77832
6.66992
7.77832
7.22168
6.66992
6.1084
7.22168
6.66992
9.43848
6.66992
6.66992
6.1084
2.77832
2.77832
2.77832
4.69238
5.56152
2.22168
5.56152
5.56152
5.0
5.56152
5.56152
2.77832
5.56152
5.56152
2.22168
2.22168
5.0
2.22168
8.33008
5.56152
5.56152
5.56152
5.56152
3.33008
5.0
2.77832
5.56152
5.0
7.22168
5.0
5.0
5.0
3.33984
2.59766
3.33984
5.83984
3.33008 -- open double quote
5.56152 -- dash/minus
3.33008 -- close double quote
6.33789
April 3, 2015
&
\
(
)
*
+
,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\\
]
^
_
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
7.22168
2.77832
3.33008
3.33008
3.8916
5.83984
2.77832
3.33008
2.77832
2.77832
5.56152
5.56152
5.56152
5.56152
5.56152
5.56152
5.56152
5.56152
5.56152
5.56152
3.33008
3.33008
5.83984
5.83984
5.83984
6.1084
9.75098
7.22168
7.22168
7.22168
7.22168
6.66992
6.1084
7.77832
7.22168
2.77832
5.56152
7.22168
6.1084
8.33008
7.22168
7.77832
6.66992
7.77832
7.22168
6.66992
6.1084
7.22168
6.66992
9.43848
6.66992
6.66992
6.1084
3.33008
2.77832
3.33008
5.83984
5.56152
2.77832
5.56152
6.1084
5.56152
6.1084
5.56152
3.33008
6.1084
6.1084
2.77832
2.77832
5.56152
2.77832
8.8916
6.1084
6.1084
6.1084
6.1084
3.8916
5.56152
44
t
u
v
w
x
y
z
{
|
}
~
\170
\177
\186
_
->
->
->
->
->
->
->
->
->
->
->
->
->
->
->
3.33008
6.1084
5.56152
7.77832
5.56152
5.56152
5.0
3.8916
2.79785
3.8916
5.83984
5.0 -- open double quote
5.56152 -- dash/minus
5.0 -- close double quote
7.22168
April 3, 2015
W
-> 7.67969
X
-> 6.45
Y
-> 7.95
Z
-> 6.10977
[
-> 3.32969
\92 -> 2.77969
]
-> 3.32969
\94 -> 6.57969
\95 -> 5.0
\96 -> 5.0
a
-> 6.30977
b
-> 5.48984
c
-> 5.48984
d
-> 4.93984
e
-> 4.43894
f
-> 5.20977
g
-> 4.10977
h
-> 6.02969
i
-> 3.28984
j
-> 6.02969
k
-> 5.48984
l
-> 5.48984
m
-> 5.75977
n
-> 5.20977
o
-> 5.48984
p
-> 5.48984
q
-> 5.20977
r
-> 5.48984
s
-> 6.02969
t
-> 4.38984
u
-> 5.75977
v
-> 7.12969
w
-> 6.85977
x
-> 4.92969
y
-> 6.85977
z
-> 4.93984
{
-> 4.8
|
-> 2.0
}
-> 4.8
~
-> 5.48984
\160 -> 7.61992
\163 -> 5.48984
\172 -> 9.86992
\179 -> 5.48984
\180 -> 5.48984
\184 -> 5.48984
\185 -> 5.48984
\216 -> 7.12969
\217 -> 6.02969
\218 -> 6.02969
_
-> 2.5
34.6.3
-----
Omega
Xi
Psi
Zeta
-- therefore
------------------------------
perp
heavy underscore
overscore
alpha
beta
chi
delta
epsilon
phi
gamma
eta
iota
var phi
kappa
lambda
mu
nu
omicron
pi
theta
rho
sigma
tau
upsilon
var pi
omega
xi
psi
zeta
------------
longer tilde
Euro
le
leftarrow
ge
times
div
ne
not
wedge/and
vee/or
Font tags
45
ftUnder :: Bool,
ftStr
:: String
w fss fs []
= FontString (reverse fs) : fss
w fss [] (Space _ : fs) = w fss [] fs
w fss fs (Space _ : fs) =
w (FontString (reverse fs) : fss) [] fs
w fss fs (f:fs)
= w fss (f : fs) fs
}
| Times10Ital {
ftUnder :: Bool,
ftStr
:: String
}
| Helvetica10 {
ftUnder :: Bool,
ftStr
:: String
}
| Helvetica10Oblique {
ftUnder :: Bool,
ftStr
:: String
}
| Helvetica10Bold {
ftUnder :: Bool,
ftStr
:: String
}
| Helvetica10BoldOblique {
ftUnder :: Bool,
ftStr
:: String
}
| Symbol10 {
ftUnder :: Bool,
ftStr
:: String
}
deriving Show
34.6.5
34.6.6
34.6.4
Font strings
FontString
into
the
Space-separated
April 3, 2015
Text encoding
fsWords f groups
FontStrings.
Font blocks
34.7
Conveniences
stroke ;
newpath ;
show ;
arc ;
moveto ;
gsave ;
lineto ;
grestore ;
translate .
newpath, moveto, lineto, closepath, stroke, show_,
arc, gsave, grestore, translate :: String
newpath
= "newpath"
moveto
= "moveto"
lineto
= "lineto"
closepath = "closepath"
46
stroke
show_
arc
gsave
grestore
translate
=
=
=
=
=
=
"stroke"
"show"
"arc"
"gsave"
"grestore"
"translate"
Draw a box .
box :: Double -> Double -> Double -> Double -> BPS
box l b r t =
let [l, b, r, t] = map show [l, b, r, t]
in ([(l, b, r, t)], [
unwords [newpath, l, b, moveto, l, t, lineto,
r, t, lineto, r, b, lineto, closepath,
stroke]
])
34.8
34.8.1
Instance declarations
EPSDrawable
([(_,b,r,_)],ps) =
epsDraw options (FontBlock fs)
in ([(l, b - 11, max r r, t)],
ps ++ [grestore] ++ ps ++
["gsave 0 -11 translate"])
35
File.Lock
elephant
epsDraw _ ft =
let w = ftWidth ft
s = psStr (case ft of
Space _ -> " "
_
-> ftStr ft)
f = case ft of
Space
_
-> "times10"
Times10
_ _ -> "times10"
Times10Ital
_ _ -> "times10ital"
Helvetica10
_ _ -> "helv10"
Helvetica10Oblique
_ _ -> "helv10obl"
Helvetica10Bold
_ _ -> "helv10bld"
Helvetica10BoldOblique _ _ -> "helv10bldobl"
Symbol10
_ _ -> "symbol10"
in ([(0, -2, w, 10)], [
"0 0 moveto " ++ f ++ " " ++ s ++ " show"
] ++ if ftUnder ft then [
"0.4 setlinewidth newpath 0 -1.2 moveto " ++
show w ++ " -1.2 lineto stroke"
] else [])
instance EPSDrawable FontString where
elephant
epsDraw options (FontString fs) =
let p :: [FontTag] -> BPS
p fs = case fs of
[]
-> ([(0,0,0,0)],[])
(f : fs) ->
let ([(l,b,r,t)],ps) = epsDraw options f
([(_,_,r,_)],ps) = p fs
in ([(l, b, r + r, t)], ps ++ [grestore] ++
ps ++ [show r ++ " 0 translate"] ++
[gsave])
in p fs
instance EPSDrawable FontBlock where
snail snail
elephant
April 3, 2015
35.1
Maintenance notes
35.2
lockFile path locks the file at path, returning True iff the file was
not already locked and was successfully locked. unlockFile path
unlocks the file at path, returning True iff the file was locked and
was successfully unlocked. isLockedFile path returns True iff the
file at path is locked.
lockFile, unlockFile, isLockedFile :: String -> IO Bool
lockFile filename = do
islocked <- isLockedFile filename
if islocked
then return False
else do writeFile (extend filename) "LOCKED\n"
return True
unlockFile filename = do
islocked <- isLockedFile filename
if islocked
then do removeFile (extend filename)
return True
else return False
isLockedFile filename = do
f <- E.catch (readFile (extend filename))
(\(_ :: E.IOException) -> return "")
return (length f > 0)
extend :: String -> String
extend filename = filename ++ ".LOCK"
35.3
47
35.4
Guards
36
File.Versions
36.4
36.2
readLatest dir root reads the contents of the latest version of the
file with the given root file name in directory dir . Either Just the
contents are returned, or Nothing if no version of the file could be
read.
readLatest :: FilePath -> FilePath -> IO (Maybe String)
readLatest dir root = do
mn <- latestName dir root
case mn of
Nothing -> return Nothing
Just name -> readFile (dir ++/++ name)
36.3
April 3, 2015
purgeVersions dir root deletes all old versions of the file with the
given root name in directory dir .
purgeVersions :: FilePath -> FilePath -> IO ()
purgeVersions dir root = do
names <- getNames dir root
let names = names \\ [latest root names]
mapM_ (removeFile . (dir ++/++)) names
36.6
removeVersions dir root deletes all versions of the file with the
given root name in directory dir .
removeVersions :: FilePath -> FilePath -> IO ()
removeVersions dir root = do
names <- getNames dir root
mapM_ (removeFile . (dir ++/++)) names
48
36.7
if existsAsD
then do
contents <- getDirectoryContents path
mapM_ (removeR . (path ++/++)) $
filter (any (/= .)) contents
removeDirectory path
else return ()
getNames dir root returns the list of filenames in directory dir that
contain the given root file name and a version number.
getNames :: FilePath -> FilePath -> IO [String]
getNames dir root = do
ls <- E.catch (getDirectoryContents dir)
(\(_ :: E.IOException) ->
error $ "Error: Directory " ++ dir
++ " can not be read.")
return $ filter (match root) ls
where
match :: String -> String -> Bool
match xs ys =
let n = length xs
in xs == take n ys && extOnly (drop n ys)
extOnly :: String -> Bool
extOnly (.:xs)
= length xs > 0 && and (map isDigit xs)
extOnly _
= False
36.8
36.10
Private routines
37
36.9
April 3, 2015
CGI
49
Data.Char
System.Environment
Numeric
Data.List
Control.Monad
qualified Control.Exception as E
qualified Data.Map as M
System.IO
import ABR.Data.List
import ABR.Text.Markup
37.1
Maintenance notes
37.2
37.6
Mime header
First things first. A CGI tool should print the magic lines identifying
the output as HTML. mimeHeader is the MIME header text, which
is printed by printMimeHeader .
mimeHeader :: String
mimeHeader = "Content-type: text/html\n"
printMimeHeader :: IO ()
printMimeHeader = putStrLn mimeHeader
37.3
Document type
37.4
37.5
April 3, 2015
put cs
50
bodyE
addressE
blockquoteE
formE
selectE
optionE
dlE
dtE
ddE
olE
ulE
dirE
menuE
liE
pE
preE
aE
mapE
areaE
citeE
codeE
emE
kbdE
sampE
strongE
varE
bE
iE
ttE
uE
tableE
captionE
trE
thE
tdE
divE
subE
supE
centerE
fontE
smallE
bigE
textareaE
h1E
h2E
h3E
h4E
h5E
h6E
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
element
"body"
"address"
"blockquote"
"form"
"select"
"option"
"dl"
"dt"
"dd"
"ol"
"ul"
"dir"
"menu"
"li"
"p"
"pre"
"a"
"map"
"area"
"cite"
"code"
"em"
"kbd"
"samp"
"strong"
"var"
"b"
"i"
"tt"
"u"
"table"
"caption"
"tr"
"th"
"td"
"div"
"sub"
"sup"
"center"
"font"
"small"
"big"
"textarea"
"h1"
"h2"
"h3"
"h4"
"h5"
"h6"
April 3, 2015
kbdN
sampN
strongN
varN
bN
iN
ttN
uN
tableN
captionN
trN
thN
tdN
subN
supN
centerN
smallN
bigN
h1N
h2N
h3N
h4N
h5N
h6N
37.7
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
kbdE
sampE
strongE
varE
bE
iE
ttE
uE
tableE
captionE
trE
thE
tdE
subE
supE
centerE
smallE
bigE
h1E
h2E
h3E
h4E
h5E
h6E
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
Standards
The html element needs to have certain attributes to meet standards. htmlT applies the attributes to go with the transitional
doctype above.
htmlT :: IO () -> IO ()
htmlT = htmlE [("xmlns", "http://www.w3.org/1999/xhtml"),
("xml:lang", "en"),
("lang", "en")]
37.8
Bailing out
If the tool wants to exit, displaying only an error message use this.
htmlError message prints an error message in HTML code. Ensure message is plain text (no tags please).
htmlError :: String -> IO ()
htmlError message = htmlT (do
headN (titleN (putStr "ERROR"))
bodyN (pN (put message))
)
37.9
CGI inputs
51
getContentLength :: IO Int
getContentLength = do
contentLength <- getEnvVar "CONTENT_LENGTH"
return (if null contentLength
then 0
else read contentLength)
getFormData reads standard input to obtain the post method inputs, decodes them and returns them in a binary search tree.
getFormData :: IO (M.Map String String)
getFormData = do
contentLength <- getContentLength
cs <- getContents
return $ M.fromList $ decodeForm $
take contentLength cs
where
decodeForm :: String -> [(String,String)]
decodeForm = map nv . chop &
nv :: String -> (String, String)
nv cs =
let [name,value] = case chop = cs of
[n,v] -> [n,v]
[n] -> [n, ""]
_
-> error $ "Cant decode: " ++
show cs
in (decode name, decode value)
decode :: String -> String
decode cs = case cs of
[]
->
[]
+ : xs
->
: decode xs
% : x1 : x2 : xs ->
toEnum ((fst . head . readHex) [x1,x2])
: decode xs
x : xs
->
x : decode xs
getFormData reads standard input to obtain the post method inputs in the enctype="multipart/form-data" format, decodes them
and returns them in a binary search tree.4
getFormData :: IO (M.Map String String)
getFormData = do
contentLength <- getContentLength
hSetBinaryMode stdin True
cs <- getContents
let cs = take contentLength cs
return $ M.fromList $ decodeForm cs
where
decodeForm :: String -> [(String, String)]
decodeForm cs =
let cs = dropWhile (/= -) cs
(bs, cs) = break isControl cs
css = init (chops ("\r\n" ++ bs) cs)
in concatMap pairs css
pairs :: String -> [(String,String)]
pairs cs =
let cs = dropWhile (/= ;) cs
" : cs = dropWhile (/= ") cs
(name,cs) = break (== ") cs
fn = "\"; filename=\""
in if fn isPrefixOf cs then
let ds = drop (length fn) cs
(filename,ds) = break (== ") ds
ds = drop 2 (dropWhile (/= :) ds)
(mimetype,ds) = break isSpace ds
in [(name, drop 4 ds),
(name ++ ".filename", filename),
(name ++ ".type", mimetype)]
else
[(name, drop 5 cs)]
For debugging forms: dumpFormData tree outputs the form inputs
in a nicely encoded XHTML fragment.
4 This function in part by Annie Lo, 2134CIT Programming
Paradigms and Languages, Advanced Studies project, 2004.
April 3, 2015
38
Daytime
38.1
Maintenance notes
38.2
Language tweaks
38.3
Data types
38.4
Lexing
52
38.5
Parsing
#> Saturday
#> Saturday
"su"
"mo"
"tu"
"we"
"th"
"fr"
"sa"
|
|
|
|
|
|
|
"sun"
"mon"
"tues"
"wed"
"thurs"
"fri"
"sat"
|
|
|
|
|
|
|
"sunday"
"monday"
"tuesday"
"wednesday"
"thursday"
"friday"
"saturday".
weekday
su
am
sun
sunday
pm
mo
mon
monday
tu
tues
tuesday
w
we
wed
wednesday
th
thurs
thursday
hours12
f
cardinal in [1..12]
fr
fri
friday
sa
saturday
cardinal in [0 .. 23]
April 3, 2015
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
#>
Sunday
Sunday
Sunday
Monday
Monday
Monday
Monday
Tuesday
Tuesday
Tuesday
Wednesday
Wednesday
Wednesday
Wednesday
Thursday
Thursday
Thursday
Friday
Friday
Friday
Friday
Saturday
cardinal in [0..59]
53
daytime
hours12
ampm
minSec
(Daytime h m s)
let ts = s tm = m in Daytime
(h - h (tm mod
(ts mod
minSec
hours24
minSec
minSec
0 0
m 0
m s
38.8
minSecP)
dayAndTime
daytime
weekday
38.6.1
Instance declarations
Showing
38.6.2
Weekday methods
dayAndTime ::=
weekday daytime
| daytime weekday.
38.6
38.7
Daytime methods
inInterval start duration time returns True iff start time <
start + duration.
inInterval :: Daytime -> Daytime -> Daytime -> Bool
inInterval start duration time =
start <= time && time < (start + duration)
showDT24 t shows the daytime t in 24 hour format suppressing the
seconds.
showDT24
showDT24
pad h
where
pad =
daytime
Arithmetic
tm div 60)
60)
60)
_ * _ = undefined "Num.*"
weekday
- (Daytime h m s) =
s
m - ts div 60
39
HaskellLexer
39.1
Maintenance notes
39.2
Language tweaks
April 3, 2015
+ (Daytime h m s) =
s
m + ts div 60
tm div 60)
60)
39.3
54
start
>
i
}
*
\n
f9
i1
i1
i2
i3
i4
i5
i6
i7
i8
i9
i10
i11
*
b
e
i2
*
f8
e
i3
d
*
f7
i4
o
i
*
f6
i5
*
n
c
*
f5
i6
*
{
{
i7
*
f4
c
i8
d
*
f3
ix
ix
ix
ix
ix
ix
ix
ix
ix
ix
ix
b
e
g
i
n
{
c
o
d
e
}
i2
i3
i4
i5
i6
i7
i8
i9
i10
i11
f
fx c a rs cps = case
[]
->
((c,p):cps)
| c == c
->
| otherwise ->
f1
f2
f3
f4
f5
f6
f7
f8
f9
=
=
=
=
=
=
=
=
=
fx
fx
fx
fx
fx
fx
fx
fx
fx
e
n
d
{
c
o
d
e
}
cps of
reverse rs
a ((c,p):rs) cps
reverse rs ++ [(c,p)] ++ f cps
f2
f3
f4
f5
f6
f7
f8
f9
(\_ cps -> i cps)
39.4
This section implements a lexer for Haskell. It is essentially complete for ASCII sources, but not for unicode sources.
programL performs the lexical analysis of any Haskell source. Apply deliterate to literate sources before lexing.
i9
Lexing scripts
f2
i10
i11
f1
lexeme
e
*
=
=
=
=
=
=
=
=
=
=
=
n
*
whitespace
programL :: Lexer
programL = listL [hwhitespaceL, lexemeL]
f
*
lexeme ::=
varid | conid | varsym | consym
| reservedop | reservedid.
| literal | special
lexeme
varid
conid
varsym
reservedop
->
->
->
->
April 3, 2015
literal
special
deliterate = i
where
i cps = case cps of
[]
((>,(_,0)):cps)
((\\,_):cps)
(_:cps)
consym
[]
f cps
i1 cps
i cps
reservedid
lexemeL :: Lexer
lexemeL =
varidL <|> conidL <|> varsymL <|> consymL
<|> hliteralL <|> specialL <|> reservedopL
<|> reservedidL
55
whitecharL :: Lexer
whitecharL =
newlineL <|> vertabL <|> formfeedL <|> spaceL
<|> tabL <|> nonbrkspcL
These are already defined in Parser.lhs.
float
char
newline
string
\n
hliteralL :: Lexer
hliteralL = integerL <|> floatL <|> charL <|> stringL
special ::=
"(" | ")" | "," | ";" | "[" | "]" | "_" | "" | "{"
| "}".
space
special
(
tab
\t
)
,
vertab
\v
_
formfeed
\f
specialL :: Lexer
specialL = (
literalL
<|> literalL
<|> literalL
<|> literalL
) %> "special"
nonbrkspc
non-breaking space
(
;
_
}
<|> literalL )
<|> literalL [
<|> literalL
<|> literalL ,
<|> literalL ]
<|> literalL {
nonbrkspcL :: Lexer
nonbrkspcL = failA "non-breaking spaces not implemented"
comment ::= "--" {any1} newline.
comment
-whitespace
newline
any1
whitestuff
whitestuff
hwhitespaceL :: Lexer
hwhitespaceL = (some whitestuffL) &%> " "
whitestuff ::= whitechar | comment | ncomment.
whitestuff
commentL :: Lexer
commentL = tokenL "--" <& many any1L <& newlineL
ncomment ::= "{-" ANYseq {ncomment ANYseq} "-}".
ncomment
{-
ANYseq
-}
ncomment
ANYseq
whitechar
comment
ncomment
whitestuffL :: Lexer
whitestuffL =
(whitecharL <|> commentL <|> ncommentL) %> " "
whitechar ::=
newline | vertab | formfeed | space | tab | nonbrkspc.
ncommentL :: Lexer
ncommentL =
tokenL "{-" <& aNYseqL
<& soft (many (ncommentL <& aNYseqL)) <& tokenL "{-"
ANYseq ::= <{any2}!{any2}("{-" | "-}") {any2}>.
ANYseq
any2
whitechar
not
newline
vertab
{any2
-}
any2
formfeed
space
tab
nonbrkspc
April 3, 2015
aNYseqL :: Lexer
aNYseqL =
soft (manyUntil any2L (tokenL "{-" <|> tokenL "-}"))
any2 ::= any1 | newline | vertab | formfeed.
56
any2
large
any1
ASClarge
newline
ISOlarge
vertab
formfeed
any2L :: Lexer
any2L = any1L <|> newlineL <|> vertabL <|> formfeedL
largeL :: Lexer
largeL = aSClargeL <|> iSOlargeL
ASClarge ::= "A" | "B" | $...$ | "Z".
ASClarge
any1
graphic
...
space
tab
nonbrkspc
any1L :: Lexer
any1L = graphicL <|> spaceL <|> tabL <|> nonbrkspcL
aSClargeL :: Lexer
aSClargeL = satisfyL isUpper "ASClarge"
ISOlarge ::= $upper case accented letters$.
ISOlarge
graphic ::=
large | small | digit | symbol | special | ":"
| "\""
| "".
graphic
large
iSOlargeL :: Lexer
iSOlargeL = failA "ISOlarge not implemented"
symbol ::=
ASCsymbol | ISOsymbol.
small
symbol
digit
ASCsymbol
symbol
ISOsymbol
special
:
symbolL :: Lexer
symbolL = aSCsymbolL <|> iSOsymbolL
ASCsymbol ::=
"!" | "#" | "$" | "%" | "&" | "*" | "+" | "."
| "/" | "<" | "=" | ">" | "?" | "@" | "\\" | "^"
| "|" | "-" | "~".
"
graphicL :: Lexer
graphicL =
largeL <|> smallL <|> digitL <|> symbolL <|> specialL
<|> literalL : <|> literalL " <|> literalL \
ASCsymbol
!
#
$
small
ASCsmall
ISOsmall
&
*
smallL :: Lexer
smallL = aSCsmallL <|> iSOsmallL
ASCsmall
<
...
>
?
@
aSCsmallL :: Lexer
aSCsmallL = satisfyL isLower "ASCsmall"
ISOsmall
iSOsmallL :: Lexer
iSOsmallL = failA "ISOsmall not implemented"
large ::= ASClarge | ISOlarge.
April 3, 2015
aSCsymbolL :: Lexer
aSCsymbolL =
57
<|>
<|>
<|>
<|>
<|>
<|>
literalL
literalL
literalL
literalL
literalL
literalL
literalL
!
%
+
<
?
^
~
<|>
<|>
<|>
<|>
<|>
<|>
literalL
literalL
literalL
literalL
literalL
literalL
#
&
.
=
@
|
<|>
<|>
<|>
<|>
<|>
<|>
literalL
literalL
literalL
literalL
literalL
literalL
$
*
/
>
\\
-
varidL :: Lexer
varidL = (
smallL <&&>
((many (smallL <|> largeL <|> digitL
<|> literalL \ <|> literalL _)) &%> "")
) %> "varid"
varidL :: Lexer
varidL =
dataSatisfies varidL
(\(((_,ident),_):_) -> not (ident elem reservedids))
conid ::= large {small | large | digit | "" | "_"}.
iSOsymbolL :: Lexer
iSOsymbolL = failA "ISOsymbol not implemented"
conid
large
small
large
digit
0
digit
...
9
digitL :: Lexer
digitL = satisfyL isDigit "digit"
octit ::= "0" | "1" | $...$ | "7".
conidL :: Lexer
conidL = (
largeL <&&>
((many (smallL <|> largeL <|> digitL <|> literalL \
<|> literalL _)) &%> "")
) %> "conid"
reservedid ::=
"case"
| "deriving"
| "import"
| "infixr"
| "newtype"
| "where".
octit
0
1
...
7
octitL :: Lexer
octitL = satisfyL (\c -> c >= 0 && c <= 7) "octit"
hexit ::= digit | "A" | $...$ | "F" | "a" | $...$ | "f".
|
|
|
|
|
"class"
"do"
"in"
"instance"
"of"
|
|
|
|
|
"data"
"else"
"infix"
"let"
"then"
|
|
|
|
|
"default"
"if"
"infixl"
"module"
"type"
reservedid
case
class
data
hexit
digit
default
deriving
do
...
else
if
import
...
in
infix
hexitL :: Lexer
hexitL = satisfyL isHexDigit "hexit"
varid ::=
<small {small | large | digit | "" | "_"}
! reservedid>.
infixl
infixr
instance
let
varid
module
small
small
large
digit
_
not
reservedid
April 3, 2015
newtype
of
then
type
where
reservedids :: [String]
reservedids = [
"case",
"class",
"data",
"default",
58
"deriving",
"import",
"infixr",
"newtype",
"where"
"do",
"in",
"instance",
"of",
"else",
"infix",
"let",
"then",
"if",
"infixl",
"module",
"type",
]
reservedidL :: Lexer
reservedidL = (
dataSatisfies varidL
(\(((_,idn),_):_) -> idn elem reservedids)
) %> "reservedid"
reservedopL :: Lexer
reservedopL = (
tokenL ".." <|> tokenL "::" <|> tokenL "=>"
<|> tokenL "=" <|> tokenL "\\" <|> tokenL "|"
<|> tokenL "<-" <|> tokenL "->" <|> tokenL "@"
<|> tokenL "~"
) %> "reservedop"
decimal ::= digit {digit}.
decimal
digit
digit
decimalL :: Lexer
decimalL = (some digitL) &%> "decimal"
symbol
symbol
octal
not
octit
reservedop
varsymL :: Lexer
varsymL = ( symbolL <&&>
((many (symbolL <|> literalL :)) &%> "")
) %> "varsym"
octit
octalL :: Lexer
octalL = (some octitL) &%> "octal"
hexadecimal ::= hexit {hexit}.
varsymL :: Lexer
varsymL =
dataSatisfies varsymL
(\(((_,sym),_):_) -> not (sym elem reservedops))
consym ::= <":" {symbol | ":"} ! reservedop>.
consym
:
symbol
hexadecimal
hexit
hexit
hexadecimalL :: Lexer
hexadecimalL = (some hexitL) &%> "hexadecimal"
integer ::= decimal
| "0o" octal | "0O" octal
| "0x" hexadecimal | "0X" hexadecimal.
integer
decimal
not
reservedop
consymL :: Lexer
consymL = ( literalL : <&&>
((many (symbolL <|> literalL :)) &%> "")
) %> "varsym"
consymL :: Lexer
consymL =
dataSatisfies consymL
(\(((_,sym),_):_) -> not (sym elem reservedops))
reservedop ::=
".." | "::" | "=" | "\\" | "|" | "<-" | "->"
| "@" | "~" | "=>".
reservedop
..
::
0o
octal
0O
octal
0x
hexadecimal
0X
hexadecimal
integerL :: Lexer
integerL = (
decimalL
<|> (literalL 0 <&&>
<|> (literalL 0 <&&>
<|> (literalL 0 <&&>
hexadecimalL)
<|> (literalL 0 <&&>
hexadecimalL)
) %> "integer"
=
float
\
decimal
decimal
|
<-
decimal
-
->
E
+
@
~
=>
reservedops :: [String]
reservedops = ["..", "::", "=", "\\", "|", "<-", "->",
"@", "~", "=>"]
April 3, 2015
floatL :: Lexer
floatL = (
decimalL <&&> literalL . <&&> decimalL <&&>
((optional ((literalL e <|> literalL E)
<&&> ((optional (literalL - <|> literalL +)
) &%> ""
)
59
<&&> decimalL
)
escape
\
charesc
) &%> ""
)
ascii
) %> "float"
decimal
octal
hexadecimal
char
graphic
not
escapeL :: Lexer
escapeL = (
literalL \\
<&&> (
charescL
<|> asciiL
<|> decimalL
<|> (literalL o <&&> octalL)
<|> (literalL x <&&> hexadecimalL)
)
) %> "escape"
\
space
escape
not
\&
charL :: Lexer
charL = (
literalL \
<&&> (
alsoNotSat
<|> spaceL
<|> alsoNotSat
)
<&&> literalL \
) %> "char"
where
not1L :: Lexer
not1L = literalL \
not2L :: Lexer
not2L = literalL \\
graphicL not1L
charesc ::=
"a" | "b" | "f" | "n" | "r" | "t" | "v" | "\"
| """ | "" | "&".
escapeL not2L
charesc
<|> literalL \\
b
f
n
r
string
"
"
v
graphic
not
"
"
&
space
escape
gap
stringL :: Lexer
stringL = (
literalL "
<&&> ((many (
alsoNotSat graphicL not1L
<|> spaceL
<|> escapeL
<|> gapL
)
) &%> ""
)
<&&> literalL "
) %> "string"
where
not1L :: Lexer
not1L = literalL " <|> literalL \\
escape ::=
April 3, 2015
charescL :: Lexer
charescL = (
literalL
<|> literalL
<|> literalL
<|> literalL
) %> "charesc"
ascii ::=
"^" cntrl
| "NUL" | "SOH"
| "ACK" | "BEL"
| "FF" | "CR"
| "DC2" | "DC3"
| "CAN" | "EM"
| "US" | "SP"
a
n
v
\
|
|
|
|
|
|
<|>
<|>
<|>
<|>
literalL
literalL
literalL
literalL
"STX" |
"BS" |
"SO" |
"DC4" |
"SUB" |
"DEL".
"ETX"
"HT"
"SI"
"NAK"
"FS"
|
|
|
|
|
b <|> literalL f
r <|> literalL t
\\ <|> literalL "
&
"EOT"
"LF"
"DLE"
"SYN"
"GS"
|
|
|
|
|
"ENQ"
"VT"
"DC1"
"ETB"
"RS"
60
cntrl
ascii
^
ASClarge
cntrl
NUL
SOH
STX
ETX
EOT
ENQ
ACK
cntrlL :: Lexer
cntrlL = (
aSClargeL
<|> literalL @ <|> literalL [
<|> literalL \\ <|> literalL ] <|> literalL ^
<|> literalL _
) %> "cntrl"
BEL
BS
HT
LF
VT
gap
FF
whitechar
\
whitechar
CR
gapL :: Lexer
gapL = (
literalL \\
<&&> ((some whitecharL) &%> "")
<&&> literalL \\
) %> "gap"
SO
SI
DLE
DC1
39.5
DC2
offside tlps applies the off-side layout rule, inserting braces and
semicolons. tlps is a list of tag-lexeme-position tuples produced by
the lexer (programL) and after all whitespace has been removed with
dropwhite. Note that scripts either start with an explicit or implicit
module header. Either case is properly handled, as is the case of
unexpectedly short scripts.
DC3
DC4
NAK
SYN
ETB
CAN
EM
SUB
FS
GS
RS
This function does the real work. The list of Ints is the stack of
pending column numbers defining on/off-side.
US
SP
DEL
asciiL :: Lexer
asciiL = (
(literalL ^ <&&> cntrlL)
<|> tokenL "NUL" <|> tokenL "SOH"
<|> tokenL "ETX" <|> tokenL "EOT"
<|> tokenL "ACK" <|> tokenL "BEL"
<|> tokenL "LF" <|> tokenL "VT"
<|> tokenL "CR" <|> tokenL "SO"
<|> tokenL "DLE" <|> tokenL "DC1"
<|> tokenL "DC3" <|> tokenL "DC4"
<|> tokenL "SYN" <|> tokenL "ETB"
<|> tokenL "EM" <|> tokenL "SUB"
<|> tokenL "GS" <|> tokenL "RS"
<|> tokenL "SP" <|> tokenL "DEL"
) %> "ascii"
cntrl ::=
<|>
<|>
<|>
<|>
<|>
<|>
<|>
<|>
<|>
<|>
tokenL
tokenL
tokenL
tokenL
tokenL
tokenL
tokenL
tokenL
tokenL
tokenL
"STX"
"ENQ"
"BST"
"FF"
"SI"
"DC2"
"NAK"
"CAN"
"FS"
"US"
April 3, 2015
61
39.6
Diagnostics
unlex tlps undoes all of the above good work by unrolling all of
the lexing of tlps. It should be very useful to check for instance that
the offside rule has been applied properly.
unlex :: TLPs -> String
unlex
= ul 0
where
ul :: Col -> TLPs -> String
ul _ []
= "\n"
ul indent (((t,le),(_,_)):tlps)
| t == "special" && le == "{"
= "{\n" ++ take (indent+3) (repeat )
++ ul (indent+3) tlps
| t == "special" && le == ";"
= "\n" ++ take (indent) (repeat ) ++ "; "
++ ul indent tlps
| t == "special" && le == "}"
= "\n" ++ take (indent-3) (repeat ) ++ "}\n"
++ ul (indent-3) tlps
| otherwise
= le ++ " " ++ ul indent tlps
39.7
This section contains functions for analysing the results of the lexing phases above without using a real (combinator) Parser. This
method might turn out to be good enough to generate the sort of
information required to create the Haskell dictionary which started
me down this path. I have also used it for logical line counting.
Call this function BEFORE the next one. promoteMethods tlps
promotes the definitions within the where clause of class declatations
to the top level.
promoteMethods :: TLPs -> TLPs
promoteMethods =
pm 0
where
pm :: Int -> TLPs -> TLPs
-- the Int = 0 for not in class, 1 = in class,
-- 2 = class with where 3, .. deeper levels
pm _ [] =
[]
pm 0 ((("reservedid","class"),p):tlps) =
(("reservedid","class"),p) : pm 1 tlps
pm 0 (tlp:tlps) =
tlp : pm 0 tlps
pm 1 ((("special",";"),p):tlps) =
(("special",";"),p) : pm 0 tlps
pm 1 ((("special","{"),p):tlps) =
(("special",";"),p) : pm 2 tlps
pm 2 ((("special","}"),p):tlps) =
(("special",";"),p) : pm 0 tlps
April 3, 2015
pm n ((("special","{"),p):tlps) =
(("special","{"),p) : pm (n+1) tlps
pm n ((("special","}"),p):tlps) =
(("special","}"),p) : pm (n-1) tlps
pm n (tlp:tlps) =
tlp : pm n tlps
This function makes it easier to pick out top-level declarations.
discardInners tlps filters out all less-than-top-level declarations,
crudely by eliminating all {stuff; stuff; ... ; stuff} sequences inside
the top-level such sequence in tlps.
discardInners :: TLPs -> TLPs
discardInners
= di 0
where
di :: Int -> TLPs -> TLPs
di _ []
= []
di level ((("special","{"),p):tlps)
| level <= 0
= (("special","{"),p) : di 1 tlps
| otherwise
= di (level+1) tlps
di level ((("special","}"),p):tlps)
| level <= 1
= (("special","}"),p) : di 0 tlps
| otherwise
= di (level-1) tlps
di level (tlp:tlps)
| level <= 1
= tlp : di level tlps
| otherwise
= di level tlps
discard tlps discards all lexemes from a TLP list, tlps, up to but not
including the next semi-colon or opening or closing brace.
discard :: TLPs -> TLPs
discard []
= []
discard ((("special","{"),p):tlps)
= ((("special","{"),p):tlps)
discard ((("special","}"),p):tlps)
= ((("special","}"),p):tlps)
discard ((("special",";"),p):tlps)
= ((("special",";"),p):tlps)
discard (_:tlps)
= discard tlps
moduleName tlps extracts the name of the module from a TLP list,
tlps, if there is one, or returns [] if there is none.
moduleName :: TLPs -> TLPs
moduleName
((("reservedid","module"),_):(("conid",name),pos):_)
= [(("module",name),pos)]
moduleName _
= []
declarations tlps a TLP list, tlps, up into its top level declarations.
declarations :: TLPs -> [TLPs]
declarations
= (d [] 0) . (drop 1) . discard
where
d :: TLPs -> Int -> TLPs -> [TLPs]
d [] _ []
= []
d [] 0 ((("special","}"),_):_)
= []
d [] n ((("special",";"),_):tlps)
= d [] n tlps
d [] n (tlp:tlps)
= d [tlp] n tlps
d (tlp:tlps) _ []
= [reverse (tlp:tlps)]
d (tlp:tlps) n ((("special","}"),pos):tlps)
| n == 0
= [reverse ((("special","}"),pos):tlp:tlps)]
| otherwise
= d ((("special","}"),pos) : tlp : tlps)
62
(n-1) tlps
d (tlp:tlps) n ((("special","{"),pos):tlps)
= d ((("special","{"),pos) : tlp : tlps)
(n+1) tlps
d (tlp:tlps) n ((("special",";"),pos):tlps)
| n == 0
= reverse ((("special",";"),pos):tlp:tlps)
: d [] 0 tlps
| otherwise
= d ((("special",";"),pos):tlp:tlps) n tlps
d (tlp:tlps) n (tlp:tlps)
= d (tlp:tlp:tlps) n tlps
declared tlps takes a top-level declaration tlps and returns the
type of declaration (as a new set of Tags), the names of the declared
objects (Lexemes) and the positions of the names of the objects
(Poss).
newtypeD ((("conid",name),pos):_)
= [(("newtype",name),pos)]
newtypeD _
= []
classD :: TLPs -> TLPs
classD tlps
= case dropContext tlps of
[]
-> classD tlps
(tlp:tlps) -> classD (tlp:tlps)
where
classD ((("conid",name),pos):_)
= [(("class",name),pos)]
classD _
= []
importD
importD
importD
importD
dropContext
dropContext
dropContext
dropContext
tlps
tlps
tlps
tlps
April 3, 2015
40
Playing Cards
Module ABR.PlayingCards provides basic data types for card playing games and problems.
module ABR.PlayingCards (
Suit(..), Rank(..), suits, ranks, Card(..), Deck,
63
R7
R8
R9
R10
Jack
Queen
King
import Data.List
import System.Random
40.1
Maintenance notes
showsPrec _ c = case c of
Suit r s -> shows r . shows s
Joker
-> showString "Jkr"
Data types
Clubs ();
:: [Rank]
= [minBound..maxBound]
:: [Suit]
= [minBound..maxBound]
40.3
showChar 7
showChar 8
showChar 9
showString "10"
showChar J
showChar Q
showChar K
Requires review.
40.2
->
->
->
->
->
->
->
Creating decks
40.5
Tests
testShuffle54 :: IO ()
testShuffle54 = do
cs <- shuffle deck54
print $ length cs
print cs
41
Poker
41.1
Maintenance notes
Requires review.
41.2
shuffle deck returns all the cards in deck in a new random order.
shuffle :: Deck -> IO Deck
shuffle cs = s (length cs) cs []
where
s n cs ds | n == 1 = return $ cs ++ ds
| otherwise = do
i <- getStdRandom (randomR (0, n-1))
let c = cs !! i
s (n - 1) (delete c cs) (c : ds)
40.4
Instance declarations
s = case s of
-> showChar C
-> showChar D
-> showChar H
-> showChar S
April 3, 2015
s = case
showChar
showChar
showChar
showChar
showChar
showChar
s of
A
2
3
4
5
6
64
41.4
allSuccRanks H returns True iff all the cards in H have consecutive ranks.
allSuccRanks :: Hand -> Bool
allSuccRanks h =
let asr rs = and $ zipWith areSuccRanks rs (tail rs)
in case sort $ map rank h of
Ace : rs -> asr (Ace : rs) || asr (rs ++ [Ace])
rs
-> asr rs
41.3
Categorisation of hands
2.
3.
4.
5.
6.
7.
8.
9.
Garbage not any of the other kinds, worth only the ranks
of its cards;
Pair two cards have the same rank and all of the other
cards have different ranks;
TwoPair there are two pairs of different ranks and the other
card is yet another rank.
Triple three cards have the same rank and the rest other
different ranks;
Straight the cards all have sequential ranks (an ace can
preceed a deuce or follow a king) and some cards have different
suits;
Flush - all cards are the same suit, but not with sequential
ranks;
FullHouse a triple and a pair;
Poker four of a kind;
StraightFlush all cards have sequential ranks and the same
suit.
isPair ,
isStraight ,
isStraightFlush
kind of hand.
isTwoPair ,
isFlush ,
isStraight ,
isFullHouse ,
isTriple ,
isPoker
and
April 3, 2015
r
->
->
->
->
s) = case r of
EQ
GT
LT
compare r r
compareCards cs cs 0 compares two list of cards starting by comparing the highest ranked cards.
compareCards :: [Card] -> [Card] -> Ordering
compareCards cs cs =
compare (reverse (sort cs)) (reverse (sort cs))
Comparison of hands
65
41.5
41.6
Tests
43
(Experimental) Data.Graph
43.1
Maintenance notes
43.2
A vertex is a value from some enumerated type and for implementation reasons must usually be an instance of classes Eq, Ord, Ix and
Show.
An edge is an ordered association two vertices. Note that we are
only dealing with unweighted graphs here.
type Edge v = (v,v)
42
SendMail
import System.Process
import System.IO
import Control.Monad
42.1
Maintenance notes
Requires review.
Reviewed 2015-02-10. Passed hlint.
42.2
Function
April 3, 2015
43.3
There are several ways to represent graphs as a Haskell data structure. The following is likely to be suitable when the graph is sparse.
newtype SGraph vertex =
SGraph (Array vertex (SparseSet vertex))
deriving (Show)
This uses an array to map each vertex v in V to the set of vertices
reachable from v in one step.
instance Graph SGraph where
mkGraph v v vvs = SGraph $
accumArray (flip insertSS) emptySS (v,v) vvs
vertices (SGraph g) = indices g
boundsG (SGraph g) = bounds g
edges (SGraph g) =
[(v,v) | v <- indices g, v <- flattenSS (g!v)]
adjacent (SGraph g) v = flattenSS (g ! v)
isAdjacent (SGraph g) v v = v elemSS (g ! v)
66
43.4
ga is a non-cyclic graph.
ga :: SGraph Int
ga = mkGraph 0 9 [
(0,1), (0,3),
(1, 2),
(3, 4), (3,5), (3, 6), (3,1)
]
gb is a cyclic graph.
gb :: SGraph Int
gb = mkGraph 0 9 [
(0,1), (0,3),
(1, 2), (1,0),
(3, 4), (3,5), (3, 6), (3,1)
]
43.5
Graph Operations
43.7
Cycles detection
43.8
43.9
Imported Stuff
43.6
Reachability
isReachable g v v returns True iff a vertex v in graph g is reachable from vertex v. A depth-first search is used. This implementation uses a mutable array so that already visited nodes can be
skipped in constant time.
isReachable :: (Ix v) => Graph v -> v -> v -> Bool
isReachable g v v = runST (do
visited <- newSTArray (bounds g) False
let ir toVisit = case toVisit of
[]
-> return False
(v:vs) -> if v == v
then return True
else do
vv <- readSTArray visited v
if vv
then ir vs
else do
writeSTArray visited v True
ir (adjacent g v ++ vs)
ir (adjacent g v)
)
reachable g v returns the list of vertices in graph g that are
reachable from vertex v. A depth-first search is used. This implementation uses a mutable array so that already visited nodes can
be skipped in constant time.
reachable :: (Ix v) => Graph v -> v -> [v]
reachable g v = runST (do
visited <- newSTArray (bounds g) False
let r toVisit rvs = case toVisit of
[]
-> return rvs
(v:vs) -> do
vv <- readSTArray visited v
if vv
then r vs rvs
else do
writeSTArray visited v True
r (adjacent g v ++ vs) (v : rvs)
r (adjacent g v) []
)
April 3, 2015
67
April 3, 2015
68
>>
>>
Connections
-> printUsage
-> execute a ""
-> execute a f
44
44.2.2
44.2.3
Results
44.2.4
Rows
44.2.5
Fields
44.1
Maintenance notes
44.2
44.2.1
A My bool is a C char.
type My_bool = CChar
A My ulonglong is supposedly a 64 bit, unsigned integer, but the
way is used implies signed is a more useful choice.
type My_ulonglong = CLLong
April 3, 2015
type MYSQL_FIELD =
()
A MYSQL FIELD OFFSET is an offset into a MySQL field list.
type MYSQL_FIELD_OFFSET = CUInt
44.2.6
Options
44.3
API Functions
69
April 3, 2015
mysql free result result frees the memory allocated for a result
set by mysql store result, mysql use result, mysql list dbs, etc.
When you are done with a result set, you must free the memory it
uses by calling this function.
foreign import ccall "mysql.h"
mysql_free_result :: Ptr MYSQL_RES -> IO ()
mysql get client info returns a string that represents the client
library version.
foreign import ccall "mysql.h"
mysql_get_client_info :: IO CString
mysql get host info mysql returns a string describing the type of
connection in use, including the server host name.
foreign import ccall "mysql.h"
mysql_get_host_info :: Ptr MYSQL -> IO CString
mysql get proto info mysql returns the protocol version used by
current connection.
foreign import ccall "mysql.h"
mysql_get_proto_info :: Ptr MYSQL -> IO CUInt
mysql get server info mysql returns a string describing the type
of connection in use, including the server host name.
foreign import ccall "mysql.h"
mysql_get_server_info :: Ptr MYSQL -> IO CString
mysql info mysql retrieves a string providing information about
the most recently executed query, but only for some statements. For
other statements, mysql info returns NULL.
foreign import ccall "mysql.h"
mysql_info :: Ptr MYSQL -> IO CString
mysql init mysql allocates or initializes a MYSQL object suitable for mysql real connect. If mysql is a null pointer (use
Foreign.nullPtr), the function allocates, initializes and returns a
new object. Otherwise the object is initialized and the address returned.
foreign import ccall "mysql.h"
mysql_init :: Ptr MYSQL -> IO (Ptr MYSQL)
mysql insert id mysql returns the ID generated for an
AUTO INCREMENT column by the previous query. Use this function
after you have performed an INSERT query into a table that contains
an AUTO INCREMENT field.
foreign import ccall "mysql.h"
mysql_insert_id :: Ptr MYSQL -> IO My_ulonglong
mysql kill mysql pid asks the server to kill the thread specified
by pid.
foreign import ccall "mysql.h"
mysql_kill :: Ptr MYSQL -> CULong -> IO CInt
mysql list dbs mysql wild returns a result set consisting of
database names on the server that match the simple regular expression specified by the wild parameter. wild may contain the
wild-card characters % or _, or may be a NULL pointer to match
all databases. Returns NULL if an error occurred.
foreign import ccall "mysql.h"
mysql_list_dbs :: Ptr MYSQL -> CString
-> IO (Ptr MYSQL_RES)
mysql list fields mysql table wild returns a result set consisting
of field names in the given table that match the simple regular
expression specified by the wild parameter. wild may contain the
wild-card characters % or _, or may be a NULL pointer to match
all fields. Returns NULL if an error occurred.
foreign import ccall "mysql.h"
mysql_list_fields :: Ptr MYSQL -> CString -> CString
-> IO (Ptr MYSQL_RES)
mysql list processes mysql returns a result set describing the
current server threads. Returns NULL if an error occurred.
foreign import ccall "mysql.h"
mysql_list_processes :: Ptr MYSQL -> IO (Ptr MYSQL_RES)
70
If null or
user is the MySQL login ID. If null, the current user is assumed.
mysql store result mysql reads and returns a pointer to the entire result for the last query, or NULL is there has been an error.
db is the database name. If not null, the connection will set the
default database to this value.
April 3, 2015
mysql thread id mysql returns the thread ID of the current connection. This value can be used as an argument to mysql kill to
kill the thread. If the connection is lost and you reconnect with
mysql ping, the thread ID will change. This means you should not
get the thread ID and store it for later. You should get it when you
need it.
foreign import ccall "mysql.h"
mysql_thread_id :: Ptr MYSQL -> IO CULong
mysql use result mysql initiates a result set retrieval but does not
actually read the result set into the client like mysql store result
does. Instead, each row must be retrieved individually by making
calls to mysql fetch row.
foreign import ccall "mysql.h"
mysql_use_result :: Ptr MYSQL -> IO (Ptr MYSQL_RES)
71
45
(Experimental)
Haskell API
MySQL
45.1
Maintenance notes
45.2
Data types
45.2.1
Connections
45.3.3
Issuing a query
45.3.4
45.3
45.3.1
Functions
Establishing a connection
myConnect host user passwd db returns CheckPass mysql if a connection could be established to the MySQL server running on host
("" = "localhost"), as user ("" = the current user), with password passwd ("" = no password), using database db ("" = no
database selected). If an error occurs, CheckFail (errNum, errMsg)
is returned.
myConnect :: String -> String -> String -> String
-> IO (CheckResult MySQL (Integer, String))
myConnect host user passwd db = do
mysql <- mysql_init nullPtr
mysql <- withCStringOrNull host (\host ->
withCStringOrNull user (\user ->
withCStringOrNull passwd (\passwd ->
withCStringOrNull db (\db ->
mysql_real_connect mysql host user
passwd db 0 nullPtr 0
)
)
)
)
if mysql == nullPtr
then do
e <- mysql_errno mysql
m <- mysql_error mysql
let e = toInteger e
m <- peekCString m
(e,m) deepSeq mysql_close mysql
return (CheckFail (e,m))
else return (CheckPass mysql)
45.3.2
Closing a connection
myClose mysql closes the connection and frees the memory it uses.
myClose :: MySQL -> IO ()
myClose = mysql_close
April 3, 2015
myFetch mysql fields fetches the results set for the last query. fields
is the number of fields that wil be returned, as reported by the last
call to myQuery. It returns CheckPass (rows, lss, csss), where rows
is the number of rows in the data set, lss is the list of lengths of each
field for each row, and csss is the list of rows of columns. In the
case of an error, CheckFail (errNum, errMsg) is returned instead.
myFetch :: MySQL -> Int
-> IO (CheckResult (Integer, [[Int]],
[[String]]) (Integer, String))
myFetch mysql fields = do
results <- mysql_store_result mysql
if results /= nullPtr
then do
rows <- mysql_num_rows results
let rows = toInteger rows
(lss,csss) <- getRows results rows fields
(lss,csss) deepSeq mysql_free_result results
return (CheckPass (rows, lss, csss))
else do
e <- mysql_errno mysql
m <- mysql_error mysql
let e = toInteger e
m <- peekCString m
return (CheckFail (e,m))
where
getRows :: Ptr MYSQL_RES -> Integer -> Int
-> IO ([[Int]], [[String]])
getRows results rows fields = gr rows
where
gr :: Integer -> IO ([[Int]], [[String]])
gr r | r <= 0 =
return ([], [])
| otherwise = do
row <- mysql_fetch_row results
ls <- mysql_fetch_lengths results
ls <- peekArray fields ls
let ls = map fromIntegral ls
row <- peekArray fields row
css <- mapM (\(l,p) -> do
cs <- peekArray l p
return $ map (toEnum . fromIntegral) cs
) (zip ls row)
(lss, csss) <- gr (r - 1)
return (ls : lss, css : csss)
This has not been tested the case of NULL field values, where the
row contains a null pointer.
72
45.4
46.3
Utilities
46
Module
TION.
(Experimental)
Database.Relational
ABR.Database.Relational
is UNDER CONSTRUC-
46.1
Maintenance notes
46.2
AString Name
| AInteger Name
| ADouble Name
deriving (Eq, Ord, Show)
46.3.1
Relational algebra
Projection of a tuple on a relation schema
46.3.2
46.3.3
Natural join
data Datum =
DNull
| DString String
| DInteger Integer
| DDouble Double
deriving (Eq, Ord, Show)
April 3, 2015
73
46.3.4
46.4
Datum operations
Union
47
(Deprecated) Data.BSTree
46.3.5
Difference
46.3.6
module ABR.Data.BSTree
{-# DEPRECATED "Use Data.Map instead." #-}
(
BSTree(..), emptyBST, nullBST, depthBST, updateBST,
deleteBST, lookupBST, memberBST, lookupGuard,
flattenBST, domBST, ranBST, countBST, leftBST,
rightBST, mapBST, pairs2BST, list2BST
)
where
47.1
Maintenance notes
Reviewed
Reviewed
Reviewed
anyway.
Reviewed
47.2
Language tweaks
Selection
46.3.7
Renaming
April 3, 2015
47.3
BSTree type
74
updateBST f key value bst returns the new tree obtained by updating bst with the key and value. If the key already exists, f is
used to combine the two values. Use (\x _ -> x) to merely replace.
47.4
BSTree operations
= True
= False
updateBST f k v
= fst . update
where
update Empty
= (Node k v Empty Empty 0, 1)
update (Node k v l r s)
| k < k
= let (l, c) = update l
c = if s >= 0 && c == 1
in balance (Node k v l r (s
| k == k
= (Node k (f v v) l r s, 0)
| otherwise
= let (r, c) = update r
c = if s <= 0 && c == 1
in balance (Node k v l r (s
then 1 else 0
+ c), c)
then 1 else 0
- c), c)
deleteBST k
= fst . delete
where
delete Empty
balance :: Ord k => (BSTree k v, Int) -> (BSTree k v, Int)
= (Empty, 0)
balance (Node k v l r s, c)
delete (Node k v l r s)
| 1 < s
| k < k
= (shiftRight (Node k v l r s), c - 1)
= let (l, c) = delete l
| s < -1
c = if s == 1 && c == -1 then -1 else 0
= (shiftLeft (Node k v l r s), c - 1)
in balance (Node k v l r (s + c), c)
| otherwise
| k == k
= (Node k v l r s, c)
= join l r s
where
| otherwise
shiftRight (Node k v l r s)
= let (r, c) = delete r
| slope l == -1
c = if s == -1 && c == -1 then -1 else 0
= rotateRight (Node k v (rotateLeft l) r s)
in balance (Node k v l r (s - c), c)
| otherwise
join Empty r _
= rotateRight (Node k v l r s)
= (r, -1)
shiftRight _ = undefined "shiftRight _"
join l r s
shiftLeft (Node k v l r s)
= let ((l, c), k, v) = split l
| slope r == 1
s = s + c
= rotateLeft (Node k v l (rotateRight r) s)
c = if s == 1 && c == -1 then -1 else 0
| otherwise
in balance (Node k v l r s, c)
= rotateLeft (Node k v l r s)
split (Node k v l Empty _)
shiftLeft _ = undefined "shiftLeft _"
= ((l, -1), k, v)
rotateRight (Node k v (Node k v l r s) r s)
split (Node k v l r s)
= let (ss, ss)
= let ((r, c), k, v) = split r
= case (s, s) of
c = if s == -1 && c == -1 then -1 else 0
( 2, 0) -> (-1, 1)
in (balance (Node k v l r (s - c), c), k, v)
( 2, 1) -> ( 0, 0)
split Empty = error
( 2, 2) -> ( 0, -1)
"ABR.Data.BSTree split Empty"
( 1, 1) -> (-1, -1)
( 1, 0) -> (-1, 0)
( 1, -1) -> (-2, 0)
lookupBST k t returns Just v, where v is the value associated with
_
-> undefined "rotateRight _ 1"
k in t, or Nothing.
in Node k v l (Node k v r r ss) ss
rotateRight _ = undefined "rotateRight _ 2"
lookupBST :: Ord k => k -> BSTree k v -> Maybe v
rotateLeft (Node k v l (Node k v l r s) s)
= let (ss, ss)
lookupBST _ Empty
= case (s, s) of
= Nothing
(-2, 0) -> ( 1, -1)
lookupBST k (Node k v l r _)
(-2, -1) -> ( 0, 0)
| k < k
= lookupBST k l
(-2, -2) -> ( 0, 1)
| k == k
= Just v
(-1, -1) -> ( 1, 1)
| otherwise = lookupBST k r
(-1, 0) -> ( 1, 0)
(-1, 1) -> ( 2, 0)
memberBST k t returns True iff k occurs in t.
_
-> undefined"rotateLeft _ 1"
in Node k v (Node k v l l ss) r ss
memberBST :: Ord k => k -> BSTree k v -> Bool
rotateLeft _ = undefined "rotateLeft _ 2"
balance (Empty, _) = error
memberBST k t
"ABR.Data.BSTree balance Empty"
= case lookupBST k t of
After inserting or deleting a node the slope at a node may be 2 or
2. balance restores the 1 slope 1 invariant.
April 3, 2015
75
48
Module ABR.Data.HashTables implements hash tables in as efficient a manner as I can, while retaining as much polymorphism as
possible. The efficiency is made possible by exploiting the mutable
arrays built into the IO monad.
module ABR.Data.HashTables
{-# DEPRECATED "Use Data.HashTable instead." #-}
(
HashTable, newHT, updateHT, lookupHT, dumpHT
) where
import Data.Array.IO
import qualified Data.Map as M
48.1
April 3, 2015
Maintenance notes
48.2
pairs2BST kvs converts an association list kvs of pairs (k, v) to a
BSTree. If there are duplicate vs for a k, only the first is retained.
(Deprecated)
Data.HashTables
Data types
48.3
newHT (lo, hi) returns a new empty hash table, where (lo, hi) is the
bounds on the array and therefore the range of the hashing function.
newHT :: (Ix ix, Ord key) =>
(ix,ix) -> IO (HashTable key ix value)
newHT range = newArray range M.empty
76
48.4
48.5
lookupHT hashFun k ht returns Just v, where v is the value associated with k in the hash table ht. If k is not in the hash table,
Nothing is returned. The function hashFun maps keys to hashing
values.
lookupHT :: (Ix ix, Ord key) =>
(key -> ix) -> key -> HashTable key ix value ->
IO (Maybe value)
lookupHT hashFun k ht = do
t <- readArray ht $ hashFun k
return $ M.lookup k t
49
(Deprecated) Data.Queue
49.1
Maintenance notes
49.2
Data type
48.6
dumpHT ht prints the hash table ht in a fairly crude format, adequate for assessment of the hashing function.
dumpHT ::
(Ix ix, Enum ix, Ord key, Show key, Show value) =>
HashTable key ix value -> IO ()
dumpHT ht = do
let put ix = do
t <- readArray ht ix
print $ M.toList t
(lo,hi) <- getBounds ht
mapM_ put [lo..hi]
49.3
Operations
48.7
Test harness
test path reads a file named path and counts the frequency of all
words. Note the example hashing function hf.
primes :: [Int]
primes =
sieve [2..]
where
sieve (x:xs) =
x : sieve [x | x <- xs, x mod x /= 0]
April 3, 2015
77
50
(Deprecated) Data.SparseSet
Module ABR.Data.SparseSet implements a set type where the elements are orderable, but too selected from too large a domain to
make an array implementation practical.
module ABR.Data.SparseSet
{-# DEPRECATED "Use Data.Set instead." #-}
(
SparseSet, emptySS, nullSS, insertSS, mkSS,
deleteSS, elemSS, notElemSS, flattenSS, list2SS,
countSS, isSubSet, unionSS, sectSS, diffSS
) where
import ABR.Data.BSTree
50.1
Maintenance notes
50.2
Data type
50.3
Operations
emptySS is {}.
emptySS :: Ord k => SparseSet k
emptySS = emptyBST
nullSS s returns True iff s = {}.
nullSS :: Ord k => SparseSet k -> Bool
nullSS = nullBST
insertSS e s returns {e} s.
insertSS :: Ord k => k -> SparseSet k -> SparseSet k
insertSS k = updateBST const k ()
51
(Deprecated) Data.Set
51.1
Maintenance notes
51.2
Data type
Set [a]
deriving (Eq)
51.3
Operations
April 3, 2015
78
(.|), (.&), (.-) :: (Ord a) => Set a -> Set a -> Set a
(Set as) .| (Set bs) = Set (umerge as bs)
where
umerge []
ys
= ys
umerge xs
[]
= xs
umerge (x:xs) (y:ys)
| x < y
= x : umerge xs
| x == y
=
umerge xs
| otherwise
= y : umerge (x:xs)
(Set as) .& (Set bs) = Set (imerge as bs)
where
imerge []
ys
= []
imerge xs
[]
= []
imerge (x:xs) (y:ys)
| x < y
=
imerge xs
| x == y
= x : imerge xs
| otherwise
=
imerge (x:xs)
(Set as) .- (Set bs) = Set (smerge as bs)
where
smerge []
ys
= []
smerge xs
[]
= xs
smerge (x:xs) (y:ys)
| x < y
= x : smerge xs
| x == y
=
smerge xs
| otherwise
=
smerge (x:xs)
(y:ys)
ys
ys
A .* B returns A B =
{A, B}.
(y:ys)
ys
ys
A .+ x returns A {x}.
(.+) :: (Ord a) => Set a -> a -> Set a
N
N
{A1 , . . . An }, where
{} = {{}},
N
A .*. B returns A B.
(Set as) .*. (Set bs) = Set [(a,b) | a <- as, b <- bs]
f
f
f
f
z xs
z xs
xs
xs
April 3, 2015
79
51.4
Instances
51.4.1
52.4.2
Ord
51.4.2
Showing
51.4.3
DeepSeq
52
(Deprecated) DeepSeq
52.4.3
Maintenance notes
52.2
List instance
52.4.4
Maybe instance
52.4.5
52.1
Tuple instances
Either instance
Class Definition
53
class
DeepSeq a where
52.3
Infix operator
52.4.1
instance
instance
instance
instance
instance
instance
instance
instance
module ABR.DeepSeq.BStree
{-# DEPRECATED
"Use Data.Map and Control.DeepSeq instead." #-}
where
import ABR.DeepSeq
import ABR.Data.BSTree
52.4
(Deprecated) DeepSeq.BStree
Instance Declarations
53.1
Maintenance notes
Simple instances
DeepSeq
DeepSeq
DeepSeq
DeepSeq
DeepSeq
DeepSeq
DeepSeq
DeepSeq
April 3, 2015
()
Bool
Char
Ordering
Integer
Int
Float
Double
where
where
where
where
where
where
where
where
{}
{}
{}
{}
{}
{}
{}
{}
53.2
Instance declaration
80
54
(Deprecated)
Logic.Qualification
54.1
Maintenance notes
54.2
Qualifiable class
54.3
Instance declarations
54.3.1
Qualification
References
[1] Graham Hutton. Higher-order functions for parsing. J. Functional Programming, 2:323343, 1992. 16
[2] Jeroen Fokker. Functional parsers. In Jeuring and Meijer [6],
pages 123. 16
[3] K. H. Rosen. Discrete Mathematics and Its Applications.
McGraw-Hill, 5th edition, 2005. 32
[4] F. Rabhi and G. Lapalme. Algorithms: A Functional Programming Approach. Addison-Wesley, 1999. 43
[5] J. Launchbury. Graph algorithms with a functional flavour. In
Jeuring and Meijer [6], pages 308331. 43
[6] Johan Jeuring and Erik Meijer, editors. Advanced Functional
Programming, volume 925 of LNCS. Springer-Verlag, 1995. 2, 5
Index
*?, 9
++-++, 46
++.++, 31
++/++, 31
+:, 11
+?, 9
.*, 79
.*., 79
.+, 79
.-, 79
.<, 79
.<-, 79
.<=, 79
.&, 79
.|, 79
:->, 26
:->-, 34
:>->, 34
<++>, 16
<&, 15
<&>, 15
April 3, 2015
<&&>, 16
<|>, 15
??, 9
@>, 15
#>, 15
#?, 9
$!!, 80
%>, 16
&>, 15
&?, 9
&%>, 16
!!!, 13, 14
ABR.CGI, 49
ABR.Control.Check, 9
ABR.Control.List, 9
ABR.Control.Map, 9
ABR.Data.BSTree, 74, 80
ABR.Data.Graph, 66
ABR.Data.HashTables, 76
ABR.Data.List, 10
ABR.Data.NameTable, 12
ABR.Data.Queue, 77
ABR.Data.Set, 78
ABR.Data.SparseSet, 78
ABR.Data.Supply, 13
ABR.Database.Relational, 73
ABR.Daytime, 52
ABR.Debug.Array, 13
ABR.Debug.IArray, 14
ABR.DeepSeq, 80
ABR.Fie.Versions, 48
ABR.File.Lock, 47
ABR.Graphics.EPS, 41
ABR.Graphics.Geometry, 40
ABR.HaskellLexer, 54
ABR.Logic.Arguments, 35
ABR.Logic.Atoms, 36
ABR.Logic.Literals, 37
ABR.Logic.Qualification, 81
ABR.Logic.QuineMcClusky, 38
ABR.Logic.Variables, 34
ABR.MySQL, 72
ABR.MySQLCBinding, 69
ABR.Parser, 14
ABR.Parser.Checks, 19
ABR.Parser.Lexers, 17
ABR.Parser.Predicates, 19
ABR.PlayingCards, 63
ABR.Poker, 64
ABR.SendMail, 66
ABR.Text.Configs, 19
ABR.Text.CSV, 27
ABR.Text.JSON, 23
ABR.Text.Markup, 27
ABR.Text.Showing, 31
ABR.Text.String, 29
ABR.Util.Args, 5
ABR.Util.Errors, 6
ABR.Util.Open, 7
ABR.Util.Pos, 7
ABR.Util.Time, 7
ABRHLibs.zip, 4
accumArray, 14
Ace, 64
addressE, 50
addressN, 51
aE, 50
allSuccRanks, 65
allUnique, 11
alsoNotSat, 15
alsoSat, 15
ampersand, 7
Analyser, 14
Angle, 40
arc, 46
areaE, 50
areAnyLocked, 47
81
areSuccRanks, 64
argListP, 36
Argument, 35
argument
in atoms, 35
argumentP, 35
arguments
in atoms, 33, 34, 36
array, 14
assertFlagMinus, 5
assertFlagPlus, 5
Atom, 36
atom, 35, 36
atomNameP, 36
atomP, 36
attachQ, 77
bagElem, 11
baseE , 50
bE, 50
beats, 65
best5, 66
better, 65
bigE, 50
bigN, 51
blockGuard, 48
blockquoteE, 50
blockquoteN, 51
bN, 51
bodyE, 50
bodyN, 51
Box, 40
box, 47
BPS, 42
bpsToEps, 42
brE , 50
brN , 50
BSTree, 74
captionE, 50
captionN, 51
Card, 64
card, 79
cardinalL, 18
cartProd, 10
catenateWith, 31
centerE, 50
centerN, 51
CFlag, 19
Check, 9
CheckFail, 9
checkLex, 19
checkParse, 19
CheckPass, 9
CheckResult, 9
chop, 12
chops, 12
CIntegral, 33
citeE, 50
citeN, 51
CList, 19
closepath, 46
Clubs, 64
CNamed, 33
codeE, 50
codeN, 51
Col, 7
collecting
constants, 35
variables, 35
combinations, 10
comp, 37
compareCards, 65
compareGroups, 65
compareHands, 65
compiling, 4
Complementable, 37
Config, 19
April 3, 2015
Configs, 20
configsL, 20
configsP, 20
cons, 15
Const, 35
Constant, 33
constant, 33, 35
constantP, 33
constants
collecting, 35
Could, 14
countBST, 76
countSS, 78
CParam, 19
createDirectory, 49
CSet, 19
CString, 33
currentTime, 8
dataSatisfies, 15
dataSatisfies, 15
dateThenTime1, 8
dateThenTime2, 8
dayAndTimeP, 54
Daytime, 52
daytimeL, 52
daytimeP, 54
ddE, 50
ddN, 51
Deck, 64
deck52, 64
deck54, 64
declarations, 62
declared, 63
DeepSeq, 36
DeepSeq, 80
deepSeq, 80
deleteBST, 75
deleteFlag, 5
deleteParam, 5
deleteSS, 78
delimiter, 7
deliterate, 54
depthBST, 75
detachQ, 77
Diamonds, 64
diffDay, 8
diffHour, 8
diffMin, 8
diffSec, 8
diffSS, 78
dirE, 50
dirN, 51
discardInners, 62
disjoint, 12
distAroundOval, 41
distribution, 4
divE, 50
dlE, 50
dlN, 51
docType, 50
domBST, 76
dropEach, 10
dropWhite, 18
Dsh, 38
dtE, 50
dtHrs, 52
dtMins, 52
dtN, 51
dtSecs, 52
dumpFormData, 52
dumpHT, 77
duplicates, 11
ED, 32
elemSS, 78
emE, 50
emN, 51
82
emptyBST, 75
emptyOptions, 5
emptyQ, 77
emptySS, 78
encodeHTML, 27
encodeHTML, 27
endA, 15
endL, 17
enString, 31
Enum mysql option, 69
EPS, 42
epsDraw, 42
EPSDrawable, 42
epsilonA, 15
errMsg, 17
Error, 14
errorA, 15
ErrorCategory, 6
eset, 78
extractQ, 77
Fail, 14
failA, 15
FD, 32
fields, 30
fileModTime, 8
findClosest, 31
findOpts, 5
findSubset, 12
fixedL, 18
fixNewlines, 31
fixNewlines, 31
FlagMinus, 5
FlagPlus, 5
FlagS, 5
flattenBST, 76
flattenSS, 78
floatL, 18
Flush, 65
FontBlock, 46
fontE, 50
FontString, 46
FontTag, 45
formatLegacyTime, 8
FormattedDouble, 32
formatTime, 8
formatUTCTime, 8
formE, 50
formfeedL, 17
fragments, 10
fragments, 10
Friday, 52
frontQ, 77
fsWidth, 46
ftStr, 45
ftUnder, 45
ftWidth, 46
FullHouse, 65
Garbage, 65
GD, 32
GeoNum, 41
getAtoms, 36
getConstants, 33
getCONTENT LENGTH, 51
getCurrentLegacyTime, 8
getCurrentLocalTime, 8
getCurrentUTCTime, 8
getCurrentZonedTime, 8
getFormData, 52
getFormData, 52
getNames, 49
getParam, 22
getPATH INFO, 51
getPos, 7
getQUERY STRING, 51
getSCRIPT NAME, 51
getScriptDirectory, 51
April 3, 2015
getVariables, 34
glob, 6
grestore, 46
ground, 34
ground1, 34
Groundable, 34
Grounding, 35
groupByRank, 64
groupBySuit, 64
gsave, 46
h1E, 50
h1N, 51
h2E, 50
h2N, 51
h3E, 50
h3N, 51
h4E, 50
h4N, 51
h5E, 50
h5N, 51
h6E, 50
h6N, 51
Hand, 64
HandType, 65
handType, 65
HasAtoms, 36
HasConstants, 33
hasConstants, 33
HashTable, 76
HasKind, 32
HasPos, 7
HasVariables, 34
hasVariables, 34
HAttributes, 50
headE, 50
headN, 51
Hearts, 64
Helvetica10, 45
Helvetica10Bold, 45
Helvetica10BoldOblique, 45
helvetica10BoldObliqueWidth, 45
helvetica10BoldWidth, 44
Helvetica10Oblique, 45
helvetica10ObliqueWidth, 44
helvetica10Width, 43
hrE , 50
hrN , 50
HTag, 50
htmlE, 50
htmlError, 51
htmlN, 51
htmlT, 51
iBox, 41
iE, 50
iGeo, 41
imgE , 50
iN, 51
inInterval, 54
inputE , 50
insertName, 13
insertParam, 5
insertSS, 78
insetBox, 41
insetSeg, 41
integerP, 33
interleave, 10
iPoint, 41
isCardinal, 19
isEmptyQ, 77
isFatal, 6
isFixed, 19
isFloat, 19
isFlush, 65
isFullHouse, 65
isGarbage, 65
isindexE , 50
83
isindexN , 50
isLockedFile, 47
isPair, 65
isPoker, 65
isProperSubset, 11
isSignedCardinal, 19
isSignedFixed, 19
isSignedFloat, 19
isStraight, 65
isStraightFlush, 65
isSubSequence, 12
isSubSet, 78
isSubset, 11
isTriple, 65
isTwoPair, 65
Jack, 64
jGet, 26
jmArray, 24
jmFalse, 24
jmNull, 24
jmNumber, 24
jmObject, 24
jmString, 24
jmTrue, 24
joinBPS, 42
Joker, 64
JPropertyName, 23
JQBool, 26
JQDbe, 26
JQElem, 26
JQElems, 26
JQInt, 26
JQIsNull, 26
JQProp, 26
JQProps, 26
JQStr, 26
JQuery, 26
JResult, 26
justifyColumn, 30
JValue, 23
kbdE, 50
kbdN, 51
Kind, 32
kind, 32
kindCheck, 32
kindCheckList, 32
Kinds, 32
King, 64
KIntegral, 32
KNamed, 32
KString, 32
KTuple, 32
kUnify, 32
KUnknown, 32
latestDate, 48
latex2html, 28
leastRightShift, 41
leftBST, 76
LegacyTime, 8
LegacyTimes, 8
Lexeme, 16
Lexer, 16
lexerL, 25
liE, 50
liN, 51
Line, 7, 41
lineNo, 17
LineSeg, 41
lineto, 46
linkE , 50
list, 79
list2BST, 76
list2SS, 78
listL, 17
Literal, 37
April 3, 2015
literalL, 16
literalP, 17
lJustify, 30
lJustify, 30
lockFile, 47
lockFiles, 47
lockGuard, 48
Logic.Constants, 33
lookupBST, 75
lookupConfig, 21
lookupFlag, 6
lookupGuard, 10, 76
lookupHT, 77
lookupName, 13
lookupParam, 6, 22
lookupQueue, 6
Makefile, 4
MakeFontTags, 46
makeFontTags, 46
makeFontTagsPrec, 46
makeFormattedDouble, 32
makeHTMLSafe, 27
makeLatexSafe, 28
makeNameArray, 13
makeTable, 30
makeTableL, 30
makeTableMR, 30
many, 15
manyUntil, 15
mapBST, 76
mapE, 50
meet, 12
memberBST, 75
menuE, 50
menuN, 51
merge, 10
metaE , 50
mimeHeader, 50
mkSS, 78
mnub, 11
moduleName, 62
Monday, 52
moveto, 46
Msg, 14
msort, 10
My bool, 69
My ulonglong, 69
myClose, 72
myConnect, 72
myFetch, 72
myQuery, 72
MYSQL, 69
MySQL, 72
mysql affected rows, 69
mysql change user, 69
mysql character set name, 69
mysql close, 69
mysql data seek, 70
mysql errno, 70
mysql error, 70
mysql fetch field, 70
mysql fetch field direct, 70
mysql fetch fields, 70
mysql fetch lengths, 70
mysql fetch row, 70
MYSQL FIELD, 69
mysql field count, 70
MYSQL FIELD OFFSET, 69
mysql field seek, 70
mysql field tell, 70
mysql free result, 70
mysql get client info, 70
mysql get host info, 70
mysql get proto info, 70
mysql get server info, 70
mysql info, 70
mysql init, 70
84
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
MYSQL
MYSQL
MYSQL
mysql
mysql
mysql
mysql
mysql
mysql
mysql
mysql
insert id, 70
kill, 70
list dbs, 70
list fields, 70
list processes, 70
list tables, 71
num fields, 71
num rows, 71
options, 71
ping, 71
query, 71
real connect, 71
real escape string, 71
real query, 71
RES, 69
ROW, 69
ROW OFFSET, 69
row seek, 71
row tell, 71
select db, 71
shutdown, 71
stat, 71
store result, 71
thread id, 71
use result, 71
NameArray, 13
nameCmp, 31
nameLT, 31
NameTable, 13
Neg, 37
neg, 37
Negatable, 37
netBox, 41
newHT, 76
newlineL, 17
newNameTable, 13
newpath, 46
newSupply, 13
nextidE , 50
nofail, 16
nofail, 16
noSuperSets, 12
notElemSS, 78
notSubSequence, 12
nullBST, 75
nullSS, 78
NullSub, 34
odiff, 11
offside, 61
OK, 14
olE, 50
olN, 51
One, 38
openTool, 7
openURL, 7
optional, 15
optionE, 50
Options, 5
OptSpec, 5
OptVal, 5
osect, 11
ounion, 12
Pair, 65
pairs2BST, 76
pam, 9
ParamMissingValue, 5
ParamQueue, 5
ParamS, 5
ParamValue, 5
Parser, 17
parsers, 35
pE, 50
peekNext, 13
permutations, 10
permutations, 10
April 3, 2015
pLiteralP, 37
pN, 51
Point, 40
Poker, 65
popTemplate, 22
Pos, 7, 37
pos, 37
powSet, 11
powSet, 11
powSet ge1, 11
powSet ge1, 11
pPlus, 12
precedes, 7
preE, 50
preLex, 16
preN, 51
printDocType, 50
printMimeHeader, 50
programL, 55
promoteMethods, 62
Prop, 36
properSublists, 11
PS, 42
psStr, 46
purgeVersions, 48
put, 50
put, 50
QMBit, 38
qmSimplify, 40
Qualifiable, 81
qualify, 81
Queen, 64
Queue, 77
QueueS, 5
R10, 64
R2, 64
R3, 64
R4, 64
R5, 64
R6, 64
R7, 64
R8, 64
R9, 64
Rank, 64
rank, 64
ranks, 64
read, 21
readFile, 49
readLatest, 48
removeR, 49
removeVersions, 48
rename, 34
replace1, 12
replaceAll, 12
returnFail, 6
returnL, 17
returnPass, 6
returnWarn, 6
rightBST, 76
rJustify, 30
rJustify, 30
sall, 79
sampE, 50
sampN, 51
sany, 79
satisfyL, 16
Saturday, 52
sectSS, 78
segToLine, 41
select, 79
selectE, 50
sendMail, 66
separate, 10
Set, 78
set, 78
85
set1, 78
setUpFonts, 42
sfoldl, 79
sfoldl1, 79
sfoldr, 79
sfoldr1, 79
shiftBoxes, 41
show , 46
showConfigs, 21
showDT24, 54
showFD, 32
Showing, 35
showWithSep, 32
showWithTerm, 32
shuffle, 64
signedCardinalL, 18
signedFixedL, 18
SimpleLit, 4
smallE, 50
smallN, 51
smap, 79
snub, 11
snull, 79
soft, 16
some, 15
someUntil, 15
sortByLength, 10
sortByRankSuit, 64
sortBySuitRank, 64
Space, 45
spaceColumns, 30
spaceL, 17
spaces, 31
Spades, 64
SparseSet, 78
split, 10
sprod, 79
ssect, 79
Straight, 65
StraightFlush, 65
stringL, 18
stroke, 46
strongE, 50
strongN, 51
styleE, 50
subBag, 11
subE, 50
subHashNames, 31
subHashNums, 31
subN, 51
subsSuffix, 12
subst, 31
Substitution, 34
substs, 31
succeedA, 14
Suit, 64
suit, 64
suits, 64
Sunday, 52
sunion, 79
supE, 50
supN, 51
Supply, 13
supplyNext, 13
Symbol10, 45
symbol10Width, 45
tabL, 17
tableE, 50
tableN, 51
Tag, 16
tagFilter, 16
tagP, 17
tdE, 50
tdN, 51
textareaE, 50
thE, 50
thN, 51
April 3, 2015
Thursday, 52
ties, 65
TimeFormat, 8
Times10, 45
Times10Ital, 45
times10ItalWidth, 43
times10Width, 42
titleE, 50
titleN, 51
TLP, 16
TLPs, 16
tokenL, 17
tomorrow, 54
total, 16
translate, 46
trE, 50
trim, 30
trim2, 12
trimN, 12
Triple, 65
trN, 51
ttE, 50
ttN, 51
Tuesday, 52
TwoPair, 65
uE, 50
ulE, 50
ulN, 51
uN, 51
unfields, 30
unionSS, 78
unlex, 62
unlockFile, 47
unlockFiles, 47
unset1, 78
unString, 31
updateBST, 75
updateConfig, 21
updateHT, 77
utcToLocalTime, 8
utcToZonedTime, 8
valueP, 25
Var, 35
varE, 50
Variable, 34
variable, 34
variableP, 34
variables
collecting, 35
varN, 51
vertabL, 17
warnMsg, 17
weCat, 6
Wednesday, 52
Weekday, 52
weekdayP, 53
WEMessage, 6
weMsg, 6
wePos, 6
WEResult, 6
whitespaceL, 18
wordWrap, 29
wrapWithinWidth, 46
writeFile, 49
writeNew, 48
writeNew, 48
writeNew, 48
yesterday, 54
Zer, 38
86