I am please to announce four package releases today. From the bottom up:
rank2classes-1.4.1
is a minor update of the library with a couple of bugfixes and adjustments. To summarize, the library exports several classes such as Rank2.Functor or Rank2.Traversable that mirror their namesakes from the base library. Where the base
class methods take a function argument of type a -> b
, the rank2classes
methods expect a natural transformation of type forall a. p a -> q a
.
The main purpose of these classes is to support a programming technique often called Higher-Kinded Data, where every record field is wrapped into a type parameter of the record type. If the records in question are recursive and form a tree, however, it turns out that the one type parameter is not enough. Which brings me to
deep-transformations-0.1
As noted above, the methods from rank2classes
operate with natural transformations which work equally forall
types. In other words, they rely on parametric polymorphism. The nodes of a typical Abstract Syntax Tree, however, belong to a number of different mutually-recursive data types: module, declaration, statement, expression, etc. We often need to apply different transformations to different node types. One might say we need to work with unnatural transformations.
The new deep-transformations
library can be described as rank2classes
that switch from parametric to ad-hoc polymorphism. The former is represented with polymorphic functions, and the latter as type class instances.
The library comes with support for attribute grammars, among other things, as the new generalization is powerful enough to support them.
grammatical-parsers-0.5
The grammatical-parsers
library leans on rank2classes
to represent both grammars and parsing results in the form of Haskell records. It comes with a number of parsers with a shared interface and different performance characteristics. Some of them support Parsing Expression Grammars, others Context-Free Grammars. Some are backtracking, others are memoizing, and two of them support left-recursive grammars.
Version 0.5 comes with several major changes. A few foundational classes have been moved to the input-parsers
library. There are two new parser-transformers that allow threading of a user-defined monad. See the change log for details.
language-oberon-0.3
The language-oberon
package provides a library and executable for the Oberon programming language. Release 0.3 uses the new functionality from grammatical-parser
and deep-transformations
to implement some new features. In particular, there’s constant
folding implemented as an attribute grammar, and the parser nows uses the left-recursive parser-tranformer to store all parsed lexemes in the AST. This enables reconstruction of the original program, with all whitespace and comments preserved.
One thing of note about this library is that it uses the finally tagless technique for constructing and re-constructing the AST. The purpose of this architecture was to enable code reuse, which leads me to
language-Modula2-0.1
This is a new package that implements a parser, re-serializer, constant folder, and pretty printer for the Modula-2 programming language. It depends on all the libraries listed above. In particular it reuses several parts of language-oberon
, starting with some of the AST node declarations. Consider it a proof of (reuse) concept.
In the future I hope to push the same concept further and add more languages while reusing more code. On the other hand, I may decide to circle back and implement code generation and/or transpilation for the existing libraries. I haven’t decided yet, and I could use some input. Some help would be even better.