I am please to announce four package releases today. From the bottom up:
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
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.
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 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 package provides a library and executable for the Oberon programming language. Release 0.3 uses the new functionality from
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
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.