Modules and Dependencies
Learning Objectives
- You know how to split Gleam code into modules and files
- You know how to import external libraries in Gleam
In Gleam, each project or package consists of an amount of modules.
Each file within /src/
is its own module.
The module names are restricted to lower case letters and underscores.
Modules can be included with the import
keyword.
External dependencies from the Gleam packages can be added
with the gleam add
command, or by editing the gleam.toml
file manually.
Additionally, the gleam.toml
file can be used to configure other properties
and metadata of the project.
Below is an example gleam.toml
file:
name = "mepl_gleam"
version = "1.0.0"
description = "MEPL Gleam material"
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "username", repo = "project" }
# links = [{ title = "Website", href = "https://gleam.run" }]
#
# For a full reference of all the available options, you can have a look at
# https://gleam.run/writing-gleam/gleam-toml/.
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
The complete schema and reference for the gleam.toml
file can be found here.
Creating and importing modules
Accessing types, functions and bindings1 declared in other modules, requires importing them.
If, for instance, src/list.gleam
has the following content:
pub type List(a) {
Cons(a, List(a))
Nil
}
pub fn map(f: fn(a) -> b, l: List(a)) -> List(b) {
case l {
Cons(h, t) -> Cons(f(h), map(f, t))
Nil -> Nil
}
}
And we’d want to use the List
type and the associated function
in another module, we’d first need to import it.
// src/main.gleam
import list.{type List, map}
fn add_one(l: List(Int)) -> List(Int) {
map(fn(a) { a + 1 }, l)
}
Visibility
In the example above, the keyword pub
is used to export
the type List
and function map
. Exporting a type, function or binding
allows them to be imported and used elsewhere.
The general rule for visibility is that a public function or type
cannot contain in its signature a private type.
For instance, the following code would not compile:
// private
type Hello {}
// public
pub fn show_hello(h: Hello) -> String {
"Hello, World"
}
The Gleam compiler gives us this helpful error when attempting to compile the code above:
error: Private type used in public interface
┌─ .../src/mepl.gleam:5:1
│
5 │ pub fn show_hello(h: Hello) -> String {
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following type is private, but is being used by this public export.
Hello
Private types can only be used within the module that defines them.
Including Gleam packages into your project
The Gleam language very young in terms of programming languages, which means that its ecosystem is also tiny. At the moment of writing, the Gleam package registry has a grand total of 774 packages (compared to, for example, the Rust package registry crates.io which has 166,423 packages).
As mentioned, adding a new package to the project is as simple as
running gleam add
with the package name.
For example, if you need to work with times and dates, which are
not implemented by the Gleam standard library, you might
want to use a library such as birl.
Running gleam add birl
will automatically figure out the
latest version of the package and add the following entry to gleam.toml
:
[dependencies]
birl = ">= 1.8.0 and < 2.0.0"
After that, we are able to use birl
in our project:
import birl
import gleam/io
pub fn main() {
let now = birl.now()
io.println(birl.to_iso8601(now))
}
$ gleam run
2024-12-26T21:55:13.466+02:00
Footnotes
-
A binding is something that is declared with the
let
orconst
keywords ↩