Skip to content

Instantly share code, notes, and snippets.

@dorchard
Last active August 29, 2015 14:04
Show Gist options
  • Save dorchard/4df935ebad0807c47b80 to your computer and use it in GitHub Desktop.
Save dorchard/4df935ebad0807c47b80 to your computer and use it in GitHub Desktop.
type level implicit parameters example (speculation)
Consider a data type representing syntax trees.
> data Expr = BinOp Expr Expr | Unop Expr
> data Stmt = Seq Stmt Stmt | Assign String Expr
Let's say I want this in a module, but I also want to be able to arbitrarily extend this AST type
in modules that import it. So, I add an extra constructor and a type parameter
to all the data type definitions:
> data Expr ext = BinOp (Expr ext) (Expr ext) | Unop (Expr ext) | Ext ext
> data Stmt ext = Seq (Stmt ext) (Stmt ext) | Assign String (Expr ext)
However, the larger the type structure, the more annoying it is to add the 'ext' parameter everywhere that
needs it. At the value-level, there is already a useful solution to this 'extension'/'configuration'
problem for value definitions using the *implicit parameters* extension. But this is not available at the type level.
Let's imagine it *is* available. Then we could write something like:
> data Expr = BinOp Expr Expr | Unop Expr | Ext ?ext
> data Stmt = Seq Stmt Stmt | Assign String Expr
The question mark signifies that '?ext' is an implicit (type) parameter.
Then we get the following kinds on our types:
> *Main> :k Expr
> Expr :: (?ext :: *) => * -> *
> *Main> :k Stmt
> Stmt :: (?ext :: *) => * -> *
We can 'discharge' the implicit parameter constraint by fixing the type with
a local type synonym:
> *Main> Assign "v" (Ext 1) where type ?ext = Int
> Assign "v" (Ext 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment