Discussion:
[Agda] Allow cyclic module imports
Martín Hötzel Escardó
2018-04-25 20:01:25 UTC
Permalink
But of course still check that any cyclic definitions within the cyclic
modules are well founded.

I don't want to put this as a feature request before we discuss this and
see the (un)desirable consequences that I haven't seen on my own.

To some extent, breaking anything into modules is arbitrary and depends
on taste. But, nevertheless, modules are useful to aid understanding
(and compilation efficiency too).

However, I often find myself creating artificial modules to break module
import cycles. And I am sure you do to.

Here is a concrete example.

I have four modules UF-Subsingletons*, two modules UF-Equiv*, two
modules UF-Retracts* because

(1) in order to define equivalence, we need to know what subsingleton
types are and some properties of them.

(2) in order to prove some properties about subsingletons, we need to
use some properties of equivalences.

(3) in order to prove some more properties of equivalences, we need to
prove some more properties of subsingletons.

(4) and then add retracts to the picture, and something analogous to
(1)-(3) takes place.

My original development was monolitic because of that. In one (big)
file, you develop things in the mathematical order they are needed.

Then I refactored it into "topics" (as above). But then the same topic
needed several modules, as explained.

Couldn't we just allow cyclic module imports, provided the total set of
definitions in all modules are well founded?

There are a number of things to consider:

(1) Is this easy to implement?

(2) Does it have conceptual / software engineering disadvantages?

Looking mathematically at the problem, I see things like this: we have a
directed acyclic graph of definitions (or replace acyclic by well
founded). Assigning them to modules amounts to quotienting this graph.
Such quotients are seldom nice - they hardly ever reflect the structured
of the unquotiented graph. In particular, in the development I am
discussing, the module-picture of the development (
http://www.cs.bham.ac.uk/~mhe/agda-new/module-graph.pdf) clearly shows
(to me) that most of the dependencies are artificial when particular
definitions in particular modules are considered.

Martin
Nils Anders Danielsson
2018-04-26 08:29:53 UTC
Permalink
Post by Martín Hötzel Escardó
(1) Is this easy to implement?
(2) Does it have conceptual / software engineering disadvantages?
I'm not quite sure what you are proposing. Is the idea to treat
everything in a module cycle as one big mutual block? Or is the idea to
still require mutual blocks for things that are mutually recursive, but
sort the mutual blocks topologically? In the latter case, should this
sorting be done after meta-variables have been resolved (in which case I
wonder how they are resolved), or based only on what the user has
written in the code? And how should independent definitions be ordered?
Or should the signature be modified so that it is no longer a list (of
mutual blocks), but some kind of DAG?
--
/NAD
Martin Escardo
2018-04-26 08:36:46 UTC
Permalink
Post by Nils Anders Danielsson
Post by Martín Hötzel Escardó
(1) Is this easy to implement?
(2) Does it have conceptual / software engineering disadvantages?
I'm not quite sure what you are proposing. Is the idea to treat
everything in a module cycle as one big mutual block?
No.
Post by Nils Anders Danielsson
Or is the idea to
still require mutual blocks for things that are mutually recursive, but
sort the mutual blocks topologically?
Yes.
Post by Nils Anders Danielsson
In the latter case, should this
sorting be done after meta-variables have been resolved (in which case I
wonder how they are resolved), or based only on what the user has
written in the code? And how should independent definitions be ordered?
Or should the signature be modified so that it is no longer a list (of
mutual blocks), but some kind of DAG?
In my example, I have a sets A, B, C of code for certain mathematical
concepts a,b,c. At the moment, I have to break things e,g. in modules
A1-A3, B1-B3, C1-C2

A1
B1
C1
B2
A2
C2
A3
B3

where the modules in each line depend on the modules in the previous
lines. I would rather have only three modules A=A1+A2+A3, B=B1+B2+B3,
and C=C1+C2, each of them cyclically importing each other, but Agda
figuring out that there is no real cyclic dependency.

Martin
Nils Anders Danielsson
2018-04-26 13:36:58 UTC
Permalink
Post by Martin Escardo
In my example, I have a sets A, B, C of code for certain mathematical
concepts a,b,c. At the moment, I have to break things e,g. in modules
A1-A3, B1-B3, C1-C2
A1
B1
C1
B2
A2
C2
A3
B3
where the modules in each line depend on the modules in the previous
lines. I would rather have only three modules A=A1+A2+A3, B=B1+B2+B3,
and C=C1+C2, each of them cyclically importing each other, but Agda
figuring out that there is no real cyclic dependency.
What about instances? Consider the following code:

data D : Set where
d₁ d₂ : D

abstract
instance
x : D
x = d₁

f : ⦃ _ : D ⦄ → D
f ⦃ y ⦄ = y

z : D
z = f

Here we have a dependency from z to x. However, one cannot see this
simply by analysing the symbols occurring in the source code. Should the
following code be accepted?

data D : Set where
d₁ d₂ : D

f : ⦃ _ : D ⦄ → D
f ⦃ y ⦄ = y

z : D
z = f

abstract
instance
x : D
x = d₁
--
/NAD
Sergei Meshveliani
2018-04-26 09:35:24 UTC
Permalink
For example, Haskell allows cyclic module import, and I used such.
A real-world library for mathematics is likely to use cyclic module
import.
But Agda is somewhat more complex, I do not know where this may lead
to.

------
Sergei
Post by Martín Hötzel Escardó
But of course still check that any cyclic definitions within the cyclic
modules are well founded.
I don't want to put this as a feature request before we discuss this and
see the (un)desirable consequences that I haven't seen on my own.
To some extent, breaking anything into modules is arbitrary and depends
on taste. But, nevertheless, modules are useful to aid understanding
(and compilation efficiency too).
However, I often find myself creating artificial modules to break module
import cycles. And I am sure you do to.
Here is a concrete example.
I have four modules UF-Subsingletons*, two modules UF-Equiv*, two
modules UF-Retracts* because
(1) in order to define equivalence, we need to know what subsingleton
types are and some properties of them.
(2) in order to prove some properties about subsingletons, we need to
use some properties of equivalences.
(3) in order to prove some more properties of equivalences, we need to
prove some more properties of subsingletons.
(4) and then add retracts to the picture, and something analogous to
(1)-(3) takes place.
My original development was monolitic because of that. In one (big)
file, you develop things in the mathematical order they are needed.
Then I refactored it into "topics" (as above). But then the same topic
needed several modules, as explained.
Couldn't we just allow cyclic module imports, provided the total set of
definitions in all modules are well founded?
(1) Is this easy to implement?
(2) Does it have conceptual / software engineering disadvantages?
Looking mathematically at the problem, I see things like this: we have a
directed acyclic graph of definitions (or replace acyclic by well
founded). Assigning them to modules amounts to quotienting this graph.
Such quotients are seldom nice - they hardly ever reflect the structured
of the unquotiented graph. In particular, in the development I am
discussing, the module-picture of the development (
http://www.cs.bham.ac.uk/~mhe/agda-new/module-graph.pdf) clearly shows
(to me) that most of the dependencies are artificial when particular
definitions in particular modules are considered.
Martin
_______________________________________________
Agda mailing list
https://lists.chalmers.se/mailman/listinfo/agda
Tom Murphy
2018-04-28 20:22:49 UTC
Permalink
Fwiw Haskell's cyclic module imports can be a real pain and most projects
don't use them. Not to discourage this line of inquiry, but as a data point!

Tom
Post by Sergei Meshveliani
For example, Haskell allows cyclic module import, and I used such.
A real-world library for mathematics is likely to use cyclic module
import.
But Agda is somewhat more complex, I do not know where this may lead
to.
------
Sergei
Post by Martín Hötzel Escardó
But of course still check that any cyclic definitions within the cyclic
modules are well founded.
I don't want to put this as a feature request before we discuss this and
see the (un)desirable consequences that I haven't seen on my own.
To some extent, breaking anything into modules is arbitrary and depends
on taste. But, nevertheless, modules are useful to aid understanding
(and compilation efficiency too).
However, I often find myself creating artificial modules to break module
import cycles. And I am sure you do to.
Here is a concrete example.
I have four modules UF-Subsingletons*, two modules UF-Equiv*, two
modules UF-Retracts* because
(1) in order to define equivalence, we need to know what subsingleton
types are and some properties of them.
(2) in order to prove some properties about subsingletons, we need to
use some properties of equivalences.
(3) in order to prove some more properties of equivalences, we need to
prove some more properties of subsingletons.
(4) and then add retracts to the picture, and something analogous to
(1)-(3) takes place.
My original development was monolitic because of that. In one (big)
file, you develop things in the mathematical order they are needed.
Then I refactored it into "topics" (as above). But then the same topic
needed several modules, as explained.
Couldn't we just allow cyclic module imports, provided the total set of
definitions in all modules are well founded?
(1) Is this easy to implement?
(2) Does it have conceptual / software engineering disadvantages?
Looking mathematically at the problem, I see things like this: we have a
directed acyclic graph of definitions (or replace acyclic by well
founded). Assigning them to modules amounts to quotienting this graph.
Such quotients are seldom nice - they hardly ever reflect the structured
of the unquotiented graph. In particular, in the development I am
discussing, the module-picture of the development (
http://www.cs.bham.ac.uk/~mhe/agda-new/module-graph.pdf) clearly shows
(to me) that most of the dependencies are artificial when particular
definitions in particular modules are considered.
Martin
_______________________________________________
Agda mailing list
https://lists.chalmers.se/mailman/listinfo/agda
_______________________________________________
Agda mailing list
https://lists.chalmers.se/mailman/listinfo/agda
Loading...