Module system

Defining a module

A module is of the following form. The module keyword stars the declaration of a module followed by its name and its body. The module declaration ends after seeing the end keyword.

-- ModuleName.juvix
module ModuleName;

end;

A Juvix project is a collection of Juvix modules inside one main project folder containing a metadata file named juvix.yaml. Each Juvix file has to define a module of the same name. The name of the module must coincide with the path of the its file respect to its project. For example, if the file is root/Data/List.juvix then the module must be called Data.List, assumming root is the project's folder.

To check that Juvix is correctly detecting your project's root, one can run the command juvix internal root File.juvix.

Importing modules

To bring into the current scope all module definitions from other external modules, one can use the import keyword along with the corresponding module name. This way, one gets all the imported names qualified.

-- A.juvix
module A;
   axiom Nat : Type;
   axiom zero : Nat;
end;

-- B.juvix
module B;
    import A;
    x : A.Nat;
    x := A.zero;

Additionally, one can open an imported module making available all its names by their unqualified name.

-- A.juvix
module A;
   axiom Nat : Type;
   axiom zero : Nat;
end;

-- B.juvix
module B;
    import A;
    open A;
    x : Nat;
    x := zero;

However, opening modules may create name collisions if you already have the imported names as definitions in the current module. In this case, Juvix will complain with an error, letting you know which symbols are ambiguous. For example, in module B below, the name a is ambiguous.

-- A.juvix
module A;
axiom A : Type;
axiom a : A;
end;

-- B.juvix
module B;
import A;
open A;
axiom a : A;

x := a;
end;

One alternative here is hiding the name a as follows.

-- B.juvix
module B;
import A;
open A hiding {a};

axiom a : A;
x := a;

end;

Now, we can use the open import syntax to simplify the import-open statements.

Instead of having:

import Prelude;
open Prelude;

We simplify it by the expression:

open import Prelude;

The hiding keyword can be used within an open-import statement.

-- B.juvix
module A;
open import A hiding {a};
axiom a : A;
x := a;
end;

Exporting symbols

The module C below does not typecheck. Both symbols, originally defined in module A, are not visible in module C after importing B. The symbols A and a are not exported by the module B. To export symbols from an imported module, one can use the public keyword at the end of the corresponing open statement. For example, in module B, after marking the import of A as public, the module C typechecks.

-- A.juvix
module A;
axiom A : Type;
axiom a : A;
end;

-- B.juvix
module B;
open import A;
end;

-- C.juvix
module C;
open import B;

x : A;
x := a;
end;

Fix:

-- B.juvix
module B;
open import A public;
end;