-
Notifications
You must be signed in to change notification settings - Fork 128
Description
Suppose that you have two modules, A and B and a module interface, I. A imports I, and B imports A. Your intention is for B is to use A without yet instantiating the import of I it is parametrized by. There are two basic kinds of ways to do this:
AinheritsB's parametrized interface i.e.Ais parametrized byIand (in some way) "passes" its parametrized instance ofItoAwhen it importsA.AdistributesB's parametrized interface over its declarations i.e. each declaration inBthat used something fromIbecomes parametrized by those things before being imported intoA. This is analogous to the "backtick" import that Cryptol used to support before this new module system.
Inheriting interfaces/parameters
Inheriting an named interface
Inheriting a named interface is currently impossible. There is no way to import an interface and pass it as a functor argument when instantiating a module that is parametrized by the same interface. It seems reasonable that you should be able to write something like (not that this uses the same syntax as #1368):
module interface I where
a : *
x : a
module A where
import I
module B where
import I
import A { I = I }
Inheriting an anonymous interface
Inheriting an anonymous interface is currently possible, but still clunky.
module A where
parameter
a : *
x : a
module B where
parameter
a_ : *
x_ : a
submodule A_inst = A where
a = a_
x = x_
import submodule A_inst
With #1368, this becomes a slightly more clean, but still requires redundant names:
module A where
parameter
a : *
x : a
module B where
parameter
a_ : *
x_ : a
import A where
a = a_
x = x_
A much better syntax for this common task of inheriting parameters would be something like the following.
module A where
parameter
a : *
x : a
module B where
import A inheriting (a, x)
This can be combined with #1368 like so:
module A where
parameter
a : *
x : a
module B where
import A inheriting (x) where
a = [8]
This is just syntax sugar for
module A where
parameter
a : *
x : a
module B where
parameter
x : [8]
import A where
a = [8]
x = x // pretend that the first x is from A, the second x is from B
(This is sort of like partial functor application)
Distributing interfaces/parameters
I call this "distributing" because it is a transformation of the form
(alpha, x) -> module A where { type A = T; f : t = a}
~~>
module A where { type A alpha x = T; f : {alpha, x} t = a}
In this way the functor's parameters are "distributed" under the module in the module's declarations (where necessary).
Since "backtick" imports were considered useful enough in Cryptol before this new module system, it's probably worth bringing back?