Skip to content

[New module system] "Inheriting" and "distributing" interfaces/parameters of imports #1373

@rybla

Description

@rybla

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:

  1. A inherits B's parametrized interface i.e. A is parametrized by I and (in some way) "passes" its parametrized instance of I to A when it imports A.
  2. A distributes B's parametrized interface over its declarations i.e. each declaration in B that used something from I becomes parametrized by those things before being imported into A. 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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    languageChanges or extensions to the languageparameterized modulesRelated to Cryptol's parameterized modules

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions