3 research outputs found
Generic Constraints for Type-Safe Embedded Programming
Domain-specific languages (DSLs) are everywhere, with applications in areas such as parser generation,
music synthesis, parallel programming and even the design of domain-specific languages.
However, while the pay-off in using a DSL may be substantial, the cost of introducing
a language may be made prohibitively high by the need to construct a supporting toolchain.
A common tactic is to embed a DSL into a general-purpose host programming language.
Existing infrastructure such as a language’s compiler or type system may be re-used, provided
that the embedding accurately captures the properties of the DSL. While the rich type systems
and orthogonal abstraction features of modern functional languages have proved particularly
capable in this regard, they are not without their shortcomings. Building type-safe functions
defined over an embedded DSL can introduce application-specific type constraints that end up
being imposed on the DSL data types themselves. At best, these constraints are unwieldy and
at worst they can limit the range of DSL expressions that can be built.
In this thesis we tackle the problem of accurately embedding a DSL’s type system into that
of the purely functional language Haskell. We present a framework for expressing application-specific
constraints at the point of a DSL expression’s use rather than when the DSL’s embedding
is defined. We show how our framework can be applied more generally to capture arbitrary
properties of a DSL expression and, in certain cases, how we may subsequently prove
additional safety properties such as the totality of a function which operates over DSL expressions.
We evaluate our techniques by illustrating their use in constructing a DSL for heterogeneous
parallel programming. However, our methods have potentially wider applications such
as context-dependent computation, which are also discussed
The constrained-monad problem
In Haskell, there are many data types that would form monads were it not for the presence of type-class constraints on the operations onthat data type. This is a frustrating problem in practice, because there is a considerable amount of support and infrastructure for monads that these data types cannot use. Using several examples,we show that a monadic computation can be restructured into a normal form such that the standard monad class can be used. The technique is not specific to monads, and we show how it can also be applied to other structures, such as applicative functors. One significant use case for this technique is domain-specific languages,where it is often desirable to compile a deep embedding of a computation to some other language, which requires restricting the types that can appear in that computation