Repository: tweag/nickel
Pull request #620 (2022-02-23 13:39:15)

Rename stdlib modules (remove trailing `s`)
Depend #619. Rename the stdlib modules to remove the trailing `s`, which is originally coming from Nix but seems not to be the norm elsewhere (ex: Rust `stdlib::array`, Ocaml `Pervasive.List`, Haskell `Data.List`, Dhall `List/xxx`, Elm `List`, etc.)


Patch:
diff --git a/benches/functions/church.ncl b/benches/functions/church.ncl
index f0249487..93b61637 100644
--- a/benches/functions/church.ncl
+++ b/benches/functions/church.ncl
@@ -14,16 +14,19 @@
   id = fun x => x,
 
   run = fun n =>
-    let orig = generate id n in
-    let encoded = lists.map encode orig in
+    let base = generate id n in
 
-    let listChurch = lists.map (fun nChurch =>
-      add (mult (encode 3) nChurch) (encode 5))
-      encoded in
-    let sumChurch = lists.fold (fun accChurch nChurch => add accChurch nChurch)
-      (encode 0) listChurch in
+    let encoded =
+      base
+      |> list.map encode
+      |> list.map (fun nChurch =>
+        add (mult (encode 3) nChurch) (encode 5))
+      |> list.fold add (encode 0) in
 
-    let list = lists.map (fun n => 3*n + 5) orig in
-    let sum = lists.foldl (fun acc n => acc + n) 0 list in
-    decode sumChurch == sum,
+    let decoded =
+      base
+      |> list.map (fun n => 3*n + 5)
+      |> list.foldl (fun acc n => acc + n) 0 in
+
+    decode encoded == decoded,
 }
diff --git a/benches/lists/fold.ncl b/benches/lists/fold.ncl
index 4a6ef4c6..8fbd27f0 100644
--- a/benches/lists/fold.ncl
+++ b/benches/lists/fold.ncl
@@ -4,29 +4,29 @@ let letter | strings.CharLiteral -> strings.CharLiteral = fun n => strings.charF
   right = {
     strings = {
       run = fun n =>
-        lists.fold (fun x y => x ++ "a") (lists.generate n (fun n => letter n))
+        list.fold (fun x y => x ++ "a") (list.generate n (fun n => letter n))
     },
     nums = {
       run = fun n =>
-        lists.fold (fun x y => x*y + (x - y)) (lists.generate n (fun n => n/2))
+        list.fold (fun x y => x*y + (x - y)) (list.generate n (fun n => n/2))
     },
-    lists_ = {
+    list_ = {
       run = fun n =>
-        lists.fold (fun x acc => [x] ++ acc) (lists.generate n (fun n => [n]))
+        list.fold (fun x acc => [x] ++ acc) (list.generate n (fun n => [n]))
     },
   },
   left = {
     strings = {
       run = fun n =>
-        lists.foldl (fun x y => x ++ "a") (lists.generate n (fun n => letter n))
+        list.foldl (fun x y => x ++ "a") (list.generate n (fun n => letter n))
     },
     nums = {
       run = fun n =>
-        lists.foldl (fun x y => x*y + (x - y)) (lists.generate n (fun n => n/2))
+        list.foldl (fun x y => x*y + (x - y)) (list.generate n (fun n => n/2))
     },
-    lists_ = {
+    list_ = {
       run = fun n =>
-        lists.foldl (fun x acc => [x] ++ acc) (lists.generate n (fun n => [n]))
+        list.foldl (fun x acc => [x] ++ acc) (list.generate n (fun n => [n]))
     },
   }
 }
diff --git a/benches/lists/map.ncl b/benches/lists/map.ncl
index 23862a05..9993ff32 100644
--- a/benches/lists/map.ncl
+++ b/benches/lists/map.ncl
@@ -1,5 +1,5 @@
 let f = { f = fun x => if (x == 0) then 0 else f (x - 1) }.f in
 {
   run = fun n =>
-    lists.map f (lists.generate functions.id n)
+    list.map f (list.generate function.id n)
 }
diff --git a/benches/lists/pipe.ncl b/benches/lists/pipe.ncl
index 3488cd26..8c4aca97 100644
--- a/benches/lists/pipe.ncl
+++ b/benches/lists/pipe.ncl
@@ -1,8 +1,8 @@
 {
   run = fun n =>
-    let l = lists.generate (fun n => n*n) n in
-    let l = lists.filter (fun n => n % 2 == 0) l in
-    let l = lists.map (fun n => [n, n+1]) l in
-    let l = lists.flatten l in
-    lists.partition (fun n => n % 2 == 0) l
+    let l = list.generate (fun n => n*n) n in
+    let l = list.filter (fun n => n % 2 == 0) l in
+    let l = list.map (fun n => [n, n+1]) l in
+    let l = list.flatten l in
+    list.partition (fun n => n % 2 == 0) l
 }
diff --git a/benches/lists/sort.ncl b/benches/lists/sort.ncl
index 88f03cc6..9c113d35 100644
--- a/benches/lists/sort.ncl
+++ b/benches/lists/sort.ncl
@@ -1,5 +1,5 @@
 let nums = [3288, 2438, 1462, 437, 17, 1929, 2595, 2702, 831, 3685, 1906, 420, 2646, 1906, 2539, 184, 299, 3455, 2320, 1471, 1812, 3837, 1000, 2097, 945, 1973, 1090, 2285, 2272, 1045, 848, 3194, 2113, 537, 1953, 561, 2082, 2416, 3182, 3660, 3379, 1458, 39, 2720, 2469, 811, 837, 548, 3021, 2961, 2860, 2092, 942, 2511, 1769, 168, 130, 2755, 2552, 1057, 2619, 1848, 2373, 2012, 2339, 2521, 3593, 2784, 3094, 2260, 1994, 690, 828, 1298, 3434, 2929, 2188, 1285, 3783, 3635, 971, 3334, 87, 1578, 1363, 533, 3634, 1874, 830, 3976, 1140, 789, 1483, 1966, 1626, 3552, 2968, 3301, 749, 2576] in
 let ascending = fun x y => if x < y then `Less else if (x == y) then `Equal else `Greater in
 {
-    run = fun n => lists.sort ascending nums
+    run = fun n => list.sort ascending nums
 }
diff --git a/benches/numeric/reduce.ncl b/benches/numeric/reduce.ncl
index 395a00ff..ad73ca65 100644
--- a/benches/numeric/reduce.ncl
+++ b/benches/numeric/reduce.ncl
@@ -1,13 +1,13 @@
 {
   sum = {
     run = fun n =>
-      let numbers = lists.generate functions.id n in
-      lists.foldl (fun acc x => acc + x) 0 numbers
+      let numbers = list.generate function.id n in
+      list.foldl (fun acc x => acc + x) 0 numbers
   },
 
   product = {
     run = fun n =>
-      let numbers = lists.generate functions.id n in
-      lists.foldl (fun acc x => acc * x) 1 numbers
+      let numbers = list.generate function.id n in
+      list.foldl (fun acc x => acc * x) 1 numbers
   },
 }
diff --git a/benches/numeric/scalar.ncl b/benches/numeric/scalar.ncl
index f3f4332a..ebd9b530 100644
--- a/benches/numeric/scalar.ncl
+++ b/benches/numeric/scalar.ncl
@@ -3,12 +3,12 @@
     if l1 == [] || l2 == [] then
       []
     else
-      [f (lists.head l1) (lists.head l2)]
-      @ map2 f (lists.tail l1) (lists.tail l2),
+      [f (list.head l1) (list.head l2)]
+      @ map2 f (list.tail l1) (list.tail l2),
 
   run = fun n =>
-    let left = lists.generate functions.id n in
-    let right = lists.generate (fun n => n*n/2) n in
+    let left = list.generate function.id n in
+    let right = list.generate (fun n => n*n/2) n in
     let prod = map2 (fun x y => x * y) left right in
-    lists.foldl (fun x y => x + y) 0 prod
+    list.foldl (fun x y => x + y) 0 prod
 }
diff --git a/benches/records/countLetters.ncl b/benches/records/countLetters.ncl
index 8075b9fe..2664d78e 100644
--- a/benches/records/countLetters.ncl
+++ b/benches/records/countLetters.ncl
@@ -1,9 +1,9 @@
 {
   run = fun s =>
     let updateDict = fun dict char =>
-      if records.has_field char dict then
+      if record.has_field char dict then
         dict -$ char & {"#{char}" = dict."#{char}" + 1}
       else
         dict & {"#{char}" = 1} in
-    lists.foldl updateDict {} (strings.chars s)
+    list.foldl updateDict {} (string.chars s)
 }
diff --git a/benches/records/merge.ncl b/benches/records/merge.ncl
index 28001c66..1008d5c4 100644
--- a/benches/records/merge.ncl
+++ b/benches/records/merge.ncl
@@ -1,19 +1,19 @@
 {
   run = fun n m =>
     let prefix = fun n =>
-      let l = lists.generate (fun _n => "a") n in
-      lists.foldl (fun x y => x ++ y) "" l in
+      let l = list.generate (fun _n => "a") n in
+      list.foldl (fun x y => x ++ y) "" l in
     let makeRecStep = fun state k =>
-      let name = state.prevName ++ (strings.from_num k) in
+      let name = state.prevName ++ (string.from_num k) in
       {
         value = state.value & {"#{name}" = {}},
         prevName = name,
       } in
-    let topList = lists.generate functions.id m in
+    let topList = list.generate function.id m in
     let makeRec = fun m =>
-      let l = lists.generate functions.id n in
-      let result = lists.foldl makeRecStep {value = {}, prevName = prefix m} l in
+      let l = list.generate function.id n in
+      let result = list.foldl makeRecStep {value = {}, prevName = prefix m} l in
       result.value in
-    let l = lists.map makeRec topList in
-    lists.foldl (fun r1 r2 => r1 & r2) {} l
+    let l = list.map makeRec topList in
+    list.foldl (fun r1 r2 => r1 & r2) {} l
 }
diff --git a/benches/serialization.rs b/benches/serialization.rs
index b0135541..e8ffda8d 100644
--- a/benches/serialization.rs
+++ b/benches/serialization.rs
@@ -9,7 +9,7 @@ fn round_trip(c: &mut Criterion) {
     path.push("benches/serialization/input.json");
 
     let content = format!(
-        "builtins.serialize `Json (import \"{}\")",
+        "builtin.serialize `Json (import \"{}\")",
         path.to_string_lossy(),
     );
 
diff --git a/doc/manual/contracts.md b/doc/manual/contracts.md
index 6cd1da8a..0b2b6012 100644
--- a/doc/manual/contracts.md
+++ b/doc/manual/contracts.md
@@ -53,25 +53,25 @@ properties. Let us see how to define our very own contract. We start the REPL
 
 ```nickel
 let IsFoo = fun label value =>
-  if builtins.is_str value then
+  if builtin.is_str value then
     if value == "foo" then
       value
     else
-      contracts.blame_with "not equal to \"foo\"" label
+      contract.blame_with "not equal to \"foo\"" label
   else
-    contracts.blame_with "not a string" label
+    contract.blame_with "not a string" label
 ```
 
 A custom contract is a function of two arguments:
 
 - A `label`. Provided by the interpreter, the label contains tracking information
-  for error reporting. Its main usage is to be passed to `contracts.blame` or
-  `contracts.blame_with` when the contract isn't satisfied.
+  for error reporting. Its main usage is to be passed to `contract.blame` or
+  `contract.blame_with` when the contract isn't satisfied.
 - The value being checked.
 
 Upon success, the contract must return the original value. We will see the reason why
 in the [laziness](#laziness) section. To signal failure, we use
-`contracts.blame` or its variant `contracts.blame_with` that takes an additional
+`contract.blame` or its variant `contract.blame_with` that takes an additional
 error message as a parameter. `blame` immediately aborts the execution and
 reports a contract violation error.
 
@@ -103,10 +103,10 @@ error, as well as various other data) is enough to understand the error. In this
 case, we can write our contract more succinctly as:
 
 ```nickel
-let IsFoo = contracts.from_predicate ((==) "foo")
+let IsFoo = contract.from_predicate ((==) "foo")
 ```
 
-`contracts.from_predicate` takes a predicate (a function of one argument that
+`contract.from_predicate` takes a predicate (a function of one argument that
 returns a boolean) and converts it to a contract. The syntax `(==)` turns the
 equality operator `==` into a function, and is a shorthand for
 `fun x y => x == y`. The partial application to `(==) "foo"` is then the function
@@ -117,9 +117,9 @@ the contract is simple enough to not require custom error message.
 Here is an example of a port number contract:
 
 ```nickel
-let Port = contracts.from_predicate (fun value =>
-  builtins.is_num value &&
-  nums.is_int value &&
+let Port = contract.from_predicate (fun value =>
+  builtin.is_num value &&
+  num.is_int value &&
   value >= 0 &&
   value <= 65535)
 ```
@@ -129,8 +129,8 @@ let Port = contracts.from_predicate (fun value =>
 Let us consider a contract for bound checking:
 
 ```nickel
-let Between5And10 = contracts.from_predicate (fun value =>
-  builtins.is_num value &&
+let Between5And10 = contract.from_predicate (fun value =>
+  builtin.is_num value &&
   value >= 5 &&
   value <= 10) in
 let MyConfig = {
@@ -141,12 +141,12 @@ let MyConfig = {
 Now, we add a new field to our schema, that must be between `0` and `1`:
 
 ```nickel
-let Between5And10 = contracts.from_predicate (fun value =>
-  builtins.is_num value &&
+let Between5And10 = contract.from_predicate (fun value =>
+  builtin.is_num value &&
   value >= 5 &&
   value <= 10) in
-let Between0And1 = contracts.from_predicate (fun value =>
-  builtins.is_num value &&
+let Between0And1 = contract.from_predicate (fun value =>
+  builtin.is_num value &&
   value >= 0 &&
   value <= 1) in
 let MyConfig = {
@@ -162,17 +162,17 @@ parameters must appear first, before the `label` and `value` arguments:
 
 ```nickel
 let Between = fun min max =>
-  contracts.from_predicate (fun value =>
+  contract.from_predicate (fun value =>
     value >= min &&
     value <= max) in
 // alternative without from_predicate
 let BetweenAlt = fun min max label value =>
-  if builtins.is_num value &&
+  if builtin.is_num value &&
      value >= min &&
      value <= max then
     value
   else
-    contracts.blame label in
+    contract.blame label in
 let MyConfig = {
   level | Between 5 10,
   strength | Between 0 1,
@@ -186,8 +186,8 @@ parametrized contracts, but note that although contracts can be functions, we
 will see soon that they can be different objects as well. Even with functions,
 contract application behaves slightly differently than bare function
 application. Thus, when manually handling a contract `contract`, do not apply it
-as a function `contract label value`, but use `contracts.apply`:
-`contracts.apply contract label value`. One example of such a contract is a
+as a function `contract label value`, but use `contract.apply`:
+`contract.apply contract label value`. One example of such a contract is a
 `Nullable` contract, that accepts a value that is either null or of some other
 given format:
 
@@ -196,7 +196,7 @@ let Nullable = fun contract label value =>
   if value == null then
     value 
   else
-    contracts.apply contract label value in
+    contract.apply contract label value in
 // succeeds
 null | Nullable Num
 // succeeds too
@@ -307,7 +307,7 @@ nickel>let MyConfig = {
     bar | Num,
 }
 nickel>let config | MyConfig = {bar = 2}
-nickel> builtins.serialize `Json config
+nickel> builtin.serialize `Json config
 "{
   "bar": 2,
   "foo": "foo"
@@ -352,7 +352,7 @@ nickel>let Secure = {
   must_be_very_secure | Bool = true,
   data | Str,
 }
-nickel>builtins.serialize `Json ({data = ""} | Secure)
+nickel>builtin.serialize `Json ({data = ""} | Secure)
 "{
   "data": "",
   "must_be_very_secure": true
@@ -416,8 +416,8 @@ A list contract checks that the value is a list and applies the parameter
 contract to each element:
 
 ```
-nickel>let VeryBig = contracts.from_predicate (fun value =>
-  builtins.is_num value
+nickel>let VeryBig = contract.from_predicate (fun value =>
+  builtin.is_num value
   && value >= 1000)
 nickel>[1000, 10001, 2] | List VeryBig
 error: contract broken by a value.
@@ -578,24 +578,24 @@ is the rationale behind contracts returning a value. Let us see:
 
 ```
 let NumBoolDict = fun label value =>
-  if builtins.is_record value then
+  if builtin.is_record value then
     let check_fields = value
-      |> records.fields
-      |> lists.foldl (fun acc field_name =>
-        if strings.is_match "^\\d+$" field_name then
+      |> record.fields
+      |> list.foldl (fun acc field_name =>
+        if string.is_match "^\\d+$" field_name then
           acc // unused and always null through iteration
         else
-          contracts.blame_with "field name `#{field_name}` is not a number" label
+          contract.blame_with "field name `#{field_name}` is not a number" label
         ) null in
 
     value
-      |> records.map (fun name value =>
+      |> record.map (fun name value =>
         let label_with_msg =
-            contracts.tag "field `#{name}` is not a boolean" label in
-        contracts.apply Bool label_with_msg value)
-      |> builtins.seq check_fields
+            contract.tag "field `#{name}` is not a boolean" label in
+        contract.apply Bool label_with_msg value)
+      |> builtin.seq check_fields
   else
-    contracts.blame_with "not a record" label
+    contract.blame_with "not a record" label
 ```
 
 There is a lot to unwrap here. Please refer to the [syntax](./syntax.md) section
@@ -609,9 +609,9 @@ For laziness, the interesting bit happens here:
 
 ```
 value
-  |> records.map (fun _name value =>
-    contracts.apply Bool label value)
-  |> builtins.seq check_fields
+  |> record.map (fun _name value =>
+    contract.apply Bool label value)
+  |> builtin.seq check_fields
 ```
 
 This is the final return value of the contract (at least when `value` is a
diff --git a/doc/manual/correctness.md b/doc/manual/correctness.md
index 3cb0c449..8d9bc3fd 100644
--- a/doc/manual/correctness.md
+++ b/doc/manual/correctness.md
@@ -79,7 +79,7 @@ nickel> f 0
 1
 
 nickel> let GreaterThan = fun bound =>
-  contracts.from_predicate (fun val => val >= bound) in
+  contract.from_predicate (fun val => val >= bound) in
 -1 | GreaterThan 10
 
 error: contract broken by value
@@ -121,7 +121,7 @@ wrap `pair.key` as a list before concatenating at line 6:
 // lib.ncl
 {
   split = fun pairs =>
-    lists.fold (fun pair acc =>
+    list.fold (fun pair acc =>
       {
         // problem: the right expression to use is [pair.key]
         keys = acc.keys @ pair.key,
@@ -254,8 +254,8 @@ You can do so by writing your own custom properties, referred to as custom
 contract from now on:
 
 ```nickel
-let OptLevel = contracts.from_predicate (fun value =>
-    lists.elem value ["O0", "O1", "O2", "O3"]) in
+let OptLevel = contract.from_predicate (fun value =>
+    list.elem value ["O0", "O1", "O2", "O3"]) in
 {
   opt_level = "O2",
 }
@@ -294,7 +294,7 @@ error: incompatible types
 ```
 
 Because `OptLevel` is a custom predicate, the typechecker can't prove that `"0"`
-concatenated with `strings.from_num 1"` is a valid optimization level. For that
+concatenated with `string.from_num 1"` is a valid optimization level. For that
 matter, even `"01" : OptLevel` doesn't typecheck. It's possible to build values
 that are accepted to be of type `OptLevel`, but it's very restricted and they
 can't really be used in a meaningful way inside typed code, beside being passed
@@ -307,7 +307,7 @@ For such custom properties, a contract is the way to go:
 ```nickel
 let level = 4 in
 {
-  opt_level | #OptLevel = "0" ++ strings.from_num level,
+  opt_level | #OptLevel = "0" ++ string.from_num level,
 }
 ```
 
@@ -322,8 +322,8 @@ error: contract broken by a value.
   │
   ┌─ repl-input-4:3:27
   │
-3 │   opt_level | OptLevel = "0" ++ strings.from_num level,
-  │                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ applied to this expression
+3 │   opt_level | OptLevel = "0" ++ string.from_num level,
+  │                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^ applied to this expression
   │
   ┌─ <unknown> (generated by evaluation):1:1
   │
diff --git a/doc/manual/syntax.md b/doc/manual/syntax.md
index e9d85077..31190117 100644
--- a/doc/manual/syntax.md
+++ b/doc/manual/syntax.md
@@ -76,7 +76,7 @@ false
 
 ### Strings
 
-Nickel can work with sequences of characters, or strings. 
+Nickel can work with sequences of characters, or strings.
 Strings are enclosed by `" ... "` for a single line string or by `m#" ... "#m` for a multiline string.
 They can be concatenated with the operator `++`.
 Strings must be UTF-8 valid.
@@ -102,7 +102,7 @@ Yes it is, indeed it is"
 > let n = 5 in "The number #{n}."
 error: Type error
 
-> let n = 5 in "The number #{strings.from_num n}."
+> let n = 5 in "The number #{string.from_num n}."
 "The number 5."
 ```
 
@@ -338,7 +338,7 @@ Examples:
     increment 41
 42
 
-> let flatten = lists.fold (@) [] in flatten [[1, 2], [3], [4, 5]]
+> let flatten = list.fold (@) [] in flatten [[1, 2], [3], [4, 5]]
 [ 1, 2, 3, 4, 5 ]
 ```
 
@@ -347,18 +347,18 @@ This operator is left-associative, so `x |> f |> g` will be interpreted as `g (f
 
 Examples:
 ```
-> "Hello World" |> strings.split " "
+> "Hello World" |> string.split " "
 ["Hello", "World"]
 
 > "Hello World"
-  |> strings.split " "
-  |> lists.head
+  |> string.split " "
+  |> list.head
 "Hello"
 
 > "Hello World"
-  |> strings.split " "
-  |> lists.head
-  |> strings.uppercase
+  |> string.split " "
+  |> list.head
+  |> string.uppercase
 "HELLO"
 ```
 
@@ -394,16 +394,16 @@ Examples:
 > 5 | Bool
 error: Blame error: contract broken by a value.
 
-> let SmallNum = contracts.from_predicate (fun x => x < 5) in
+> let SmallNum = contract.from_predicate (fun x => x < 5) in
 1 | SmallNum
 1
 
-> let SmallNum = contracts.from_predicate (fun x => x < 5) in
+> let SmallNum = contract.from_predicate (fun x => x < 5) in
 10 | SmallNum
 error: Blame error: contract broken by a value.
 
-> let SmallNum = contracts.from_predicate (fun x => x < 5) in
-  let NotTooSmallNum = contracts.from_predicate (fun x => x >= 2) in
+> let SmallNum = contract.from_predicate (fun x => x < 5) in
+  let NotTooSmallNum = contract.from_predicate (fun x => x >= 2) in
   3 | Num
     | SmallNum
     | NotTooSmallNum
diff --git a/doc/manual/types-vs-contracts.md b/doc/manual/types-vs-contracts.md
index b64ed581..2b033ea0 100644
--- a/doc/manual/types-vs-contracts.md
+++ b/doc/manual/types-vs-contracts.md
@@ -22,7 +22,7 @@ What to do depends on the context:
     and are generally short functions passed as arguments to typed higher-order
     functions, which will apply a guarding contract.
 
-    Example: `lists.map (fun x => x + 1) [1,2,3]`
+    Example: `list.map (fun x => x + 1) [1,2,3]`
 - *Let-bound function outside of typed block: use a type annotation.* Even if
     local to a file, if your function is bound to a variable, it can be
     potentially reused in different places.
@@ -44,7 +44,7 @@ What to do depends on the context:
 
     let foo : Num =
       let ev : ((Num -> Num) -> Num) -> Num -> Num
-        = fun f x => f (functions.const x) in
+        = fun f x => f (function.const x) in
       ev (fun f => f 0) 1
     in ...
     ```
@@ -79,7 +79,7 @@ let Schema = {
 ## Computation (compound expressions)
 
 Some expressions are neither immediate data nor functions. Take for example the
-function application `lists.map (fun s => "http://#{s}/index") servers`.
+function application `list.map (fun s => "http://#{s}/index") servers`.
 Usually, you should do **nothing**.
 
 - *Inside configuration: nothing*. The function or operator you are using should
diff --git a/doc/manual/typing.md b/doc/manual/typing.md
index 8cd35428..23615db1 100644
--- a/doc/manual/typing.md
+++ b/doc/manual/typing.md
@@ -14,8 +14,8 @@ By default, Nickel code is dynamically typed. For example:
   name = "hello",
   version = "0.1.1",
   fullname =
-    if builtins.is_num version then
-      "hello-v#{strings.fromNum version}"
+    if builtin.is_num version then
+      "hello-v#{string.from_num version}"
     else
       "hello-#{version}",
 }
@@ -30,8 +30,8 @@ example:
   name = "hello",
   version = "0.1.1",
   fullname =
-    if builtins.is_num version then
-      "hello-v#{strings.fromNum version}"
+    if builtin.is_num version then
+      "hello-v#{string.from_num version}"
     else
       "hello-#{version + 1}",
 }
@@ -59,7 +59,7 @@ are using functions. Say we want to filter over a list of elements:
 
 ```nickel
 let filter = fun pred l =>
-  lists.foldl (fun acc x => if pred x then acc @ [x] else acc) [] l in
+  list.foldl (fun acc x => if pred x then acc @ [x] else acc) [] l in
 filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
 ```
 
@@ -68,7 +68,7 @@ Result:
 error: Type error
   ┌─ repl-input-11:2:32
   │
-2 │   lists.foldl (fun acc x => if pred x then acc @ [x] else acc) [] l in
+2 │   list.foldl (fun acc x => if pred x then acc @ [x] else acc) [] l in
   │                                ^^^^^^ This expression has type Num, but Bool was expected
 3 │ filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
   │                                                             - evaluated to this
@@ -117,7 +117,7 @@ a type annotation at the top-level:
 
 ```nickel
 (let filter = fun pred l =>
-     lists.foldl (fun acc x => if pred x then acc @ [x] else acc) [] l in
+     list.foldl (fun acc x => if pred x then acc @ [x] else acc) [] l in
 filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]) : List Num
 ```
 
@@ -169,7 +169,7 @@ The following type constructors are available:
   Example:
   ```nickel
   let x : List (List Num) = [[1,2], [3,4]] in
-  lists.flatten x : List Num
+  list.flatten x : List Num
   ```
 - **Record**: `{field1: T1, .., fieldn: Tn}`. A record whose field
   names are known statically as `field1`, .., `fieldn`, respectively of type
@@ -187,7 +187,7 @@ The following type constructors are available:
   Example:
   ```nickel
   let occurences : {_: Num} = {a = 1, b = 3, c = 0} in
-  records.map (fun char count => count + 1) occurences : {_ : Num}
+  record.map (fun char count => count + 1) occurences : {_ : Num}
   ```
 - **Enum**: `<tag1, .., tagn>`: an enumeration comprised of alternatives `tag1`,
   .., `tagn`. An enumeration literal is prefixed with a backtick and serialized
@@ -243,7 +243,7 @@ well:
 
 ```nickel
 {
-  foo : List Str = filter (fun s => strings.length s > 2) ["a","ab","abcd"],
+  foo : List Str = filter (fun s => string.length s > 2) ["a","ab","abcd"],
   bar : List Num = filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6],
 }
 ```
@@ -275,7 +275,7 @@ the typechecker surprisingly rejects our code:
 ```nickel
 (let filter = ... in
 let result = filter (fun x => x % 2 == 0) [1,2,3,4,5,6] in
-let dummy = filter (fun s => strings.length s > 2) ["a","ab","abcd"] in
+let dummy = filter (fun s => string.length s > 2) ["a","ab","abcd"] in
 result) : List Num
 ```
 
@@ -284,8 +284,8 @@ Result:
 error: Incompatible types
   ┌─ repl-input-35:2:37
   │
-2 │ let dummy = filter (fun s => strings.length s > 2) ["a","ab","abcd"] in
-  │                                             ^ this expression
+2 │ let dummy = filter (fun s => string.length s > 2) ["a","ab","abcd"] in
+  │                                            ^ this expression
   │
   = The type of the expression was expected to be `Str`
   = The type of the expression was inferred to be `Num`
@@ -427,7 +427,7 @@ We'll now explore how typed and untyped code interact.
 Until now, we have written the statically typed `filter` examples using
 statically typed blocks that enclosed both the definition of `filter` and the
 call sites. More realistically, `filter` would be a statically typed library
-function (it is actually part of the standard library as `lists.filter`) and
+function (it is actually part of the standard library as `list.filter`) and
 likely be called from dynamically typed configuration files. In this situation,
 the call site escapes the typechecker. Thus, without an additional mechanism,
 static typing would only ensure that the implementation of `filter` doesn't
@@ -439,10 +439,10 @@ an error from within `filter`.
 
 Fortunately, Nickel does have a mechanism to prevent this from happening and to
 provide good error reporting in this situation. Let us see that by ourselves by
-calling to the statically typed `lists.filter` from dynamically typed code:
+calling to the statically typed `list.filter` from dynamically typed code:
 
 ```nickel
-lists.filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
+list.filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
 ```
 
 Result:
@@ -455,8 +455,8 @@ error: Blame error: contract broken by the caller.
   │
   ┌─ repl-input-45:1:67
   │
-1 │ lists.filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
-  │                                                                   - evaluated to this expression
+1 │ list.filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
+  │                                                                  - evaluated to this expression
   │
   = This error may happen in the following situation:
     1. A function `f` is bound by a contract: e.g. `(Num -> Num) -> Num`.
@@ -466,7 +466,7 @@ error: Blame error: contract broken by the caller.
   = Note: this is an illustrative example. The actual error may involve deeper nested functions calls.
 
 note:
-    ┌─ <stdlib/lists>:160:14
+    ┌─ <stdlib/list>:160:14
     │
 160 │     filter : forall a. (a -> Bool) -> List a -> List a
     │              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bound here
@@ -475,8 +475,8 @@ note:
 note:
   ┌─ repl-input-45:1:1
   │
-1 │ lists.filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
-  │ -------------------------------------------------------------------- (3) calling <func>
+1 │ list.filter (fun x => if x % 2 == 0 then x else null) [1,2,3,4,5,6]
+  │ ------------------------------------------------------------------- (3) calling <func>
 ```
 
 We call `filter` from a dynamically typed location, but still get a spot-on
@@ -611,8 +611,8 @@ technically use custom contracts as any other type inside a static type
 annotation.
 
 ```nickel
-let Port = contracts.from_predicate (fun value =>
-  builtins.is_num value
+let Port = contract.from_predicate (fun value =>
+  builtin.is_num value
   && value % 1 == 0
   && value >= 0
   && value <= 65535) in
diff --git a/examples/README.md b/examples/README.md
index e38e8939..90f93684 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -53,11 +53,11 @@ nickel>
 
     nickel>
     ```
-- Use `builtins.serialize` to have the same behavior as the `export` subcommand
+- Use `builtin.serialize` to have the same behavior as the `export` subcommand
   and print the result as JSON:
 
   ```
-  nickel> builtins.serialize `Json (import "merge-main.ncl")
+  nickel> builtin.serialize `Json (import "merge-main.ncl")
   "{
       \"firewall\": {
       ...
diff --git a/examples/config-gcc/config-gcc.ncl b/examples/config-gcc/config-gcc.ncl
index ee01c987..8628b5d9 100644
--- a/examples/config-gcc/config-gcc.ncl
+++ b/examples/config-gcc/config-gcc.ncl
@@ -4,51 +4,51 @@ let GccFlag =
   // We only allow the following flags
   let available = ["W", "c", "S", "e", "o"] in
   fun label value =>
-  if builtins.is_str value then
-    if strings.length value > 0 &&
-      lists.any (fun x => x == strings.substring 0 1 value) available then
+  if builtin.is_str value then
+    if string.length value > 0 &&
+      list.any (fun x => x == string.substring 0 1 value) available then
       value
     else
-      contracts.blame_with "unknown flag #{value}" label
-  else if builtins.is_record value then
-    if records.has_field "flag" value && records.has_field "arg" value then
-      if lists.any (fun x => x == value.flag) available then
+      contract.blame_with "unknown flag #{value}" label
+  else if builtin.is_record value then
+    if record.has_field "flag" value && record.has_field "arg" value then
+      if list.any (fun x => x == value.flag) available then
         //Normalize the tag to a string
         value.flag ++ value.arg
       else
-        contracts.blame_with "unknown flag #{value.flag}" label
+        contract.blame_with "unknown flag #{value.flag}" label
     else
-      contracts.blame_with
+      contract.blame_with
         "bad record structure: missing field `flag` or `arg`"
         label
   else
-    contracts.blame_with "expected record or string" label in
+    contract.blame_with "expected record or string" label in
 
 let Path =
   let pattern = m#"^(.+)/([^/]+)$"#m in
   fun label value =>
-    if builtins.is_str value then
-      if strings.is_match pattern value then
+    if builtin.is_str value then
+      if string.is_match pattern value then
         value
       else
-        contracts.blame_with "invalid path" label
+        contract.blame_with "invalid path" label
     else
-      contracts.blame_with "not a string" label in
+      contract.blame_with "not a string" label in
 
 let SharedObjectFile = fun label value =>
-  if builtins.is_str value then
-    if strings.is_match m#"\.so$"#m value then
+  if builtin.is_str value then
+    if string.is_match m#"\.so$"#m value then
       value
     else
-      contracts.blame_with "not an .so file" label
+      contract.blame_with "not an .so file" label
   else
-    contracts.blame_with "not a string" label in
+    contract.blame_with "not a string" label in
 
 let OptLevel = fun label value =>
   if value == 0 || value == 1 || value == 2 then
     value
   else
-    contracts.blame label in
+    contract.blame label in
 
 let Contract = {
   path_libc | doc "Path to libc."
diff --git a/examples/lists/README.md b/examples/lists/README.md
index 395c0bf2..91cc36c0 100644
--- a/examples/lists/README.md
+++ b/examples/lists/README.md
@@ -2,7 +2,7 @@
 
 This example shows how to write generic, statically typed functions in Nickel.
 The code is illustrative: in practice, you should use the list stdlib functions
-`lists.map` and `lists.fold` instead of redefining your own.
+`list.map` and `list.fold` instead of redefining your own.
 
 ## Run
 
diff --git a/examples/lists/lists.ncl b/examples/lists/lists.ncl
index d3f52473..1c9052b6 100644
--- a/examples/lists/lists.ncl
+++ b/examples/lists/lists.ncl
@@ -1,21 +1,21 @@
 // Example list functions. This code is illustrative: prefer using the list
-// stdlib functions `lists.map` and `lists.fold` instead.
+// stdlib functions `list.map` and `list.fold` instead.
 let my_list_lib = {
-  map : forall a b. (a -> b) -> List a -> List b = fun f list =>
-    if list == [] then
+  map : forall a b. (a -> b) -> List a -> List b = fun f l =>
+    if l == [] then
       []
     else
-      let head = lists.head list in
-      let tail = lists.tail list in
+      let head = list.head l in
+      let tail = list.tail l in
       [f head] @ map f tail,
 
   fold : forall a b. (a -> b -> b) -> List a -> b -> b =
-      fun f list first =>
-        if list == [] then
+      fun f l first =>
+        if l == [] then
           first
         else
-          let head = lists.head list in
-          let tail = lists.tail list in
+          let head = list.head l in
+          let tail = list.tail l in
           f head (fold f tail first),
 } in
 // Compute `7!`
diff --git a/examples/record-contract/record-contract.ncl b/examples/record-contract/record-contract.ncl
index 232abe2d..abcaae44 100644
--- a/examples/record-contract/record-contract.ncl
+++ b/examples/record-contract/record-contract.ncl
@@ -2,8 +2,8 @@
 // Kubernetes configuration.
 // Schema and example derived from https://github.com/kubernetes/examples/blob/master/guestbook-go/guestbook-controller.json.
 
-let Port | doc "A contract for a port number" = contracts.from_predicate (fun value =>
-  builtins.is_num value &&
+let Port | doc "A contract for a port number" = contract.from_predicate (fun value =>
+  builtin.is_num value &&
   value % 1 == 0 &&
   value >= 0 &&
   value <= 65535) in
@@ -34,7 +34,7 @@ let KubernetesConfig = {
   },
 
   spec = {
-    replicas | nums.PosNat
+    replicas | num.PosNat
              | doc "The number of replicas"
              | default = 1,
 
diff --git a/examples/simple-contracts/README.md b/examples/simple-contracts/README.md
index 49e6fee0..b39d4e8f 100644
--- a/examples/simple-contracts/README.md
+++ b/examples/simple-contracts/README.md
@@ -12,7 +12,7 @@ expected to fail, to demonstrate basic error-reporting for contracts.
 For illustrative purpose, those contracts are written as plain custom contracts:
 functions `Lbl -> Dyn -> Dyn`. However, they are just boolean predicates here.
 In this case, you should rather write them more succintly as predicates `Dyn ->
-Bool` and use `contracts.fromPred` to obtain the corresponding contracts.
+Bool` and use `contract.fromPred` to obtain the corresponding contracts.
 
 ## Run
 
diff --git a/examples/simple-contracts/simple-contract-bool.ncl b/examples/simple-contracts/simple-contract-bool.ncl
index 411daa4f..150c56f2 100644
--- a/examples/simple-contracts/simple-contract-bool.ncl
+++ b/examples/simple-contracts/simple-contract-bool.ncl
@@ -1,11 +1,11 @@
 // Example of simple custom contract, parametrized by a first argument.
 // In practice, for this kind of simple predicate, one should rather use
-// `contracts.from_predicate`
+// `contract.from_predicate`
 let EqualsTo = fun reference_value label value =>
   if reference_value == value then
     value
   else
-    contracts.blame label in
+    contract.blame label in
 
 let AlwaysTrue = EqualsTo true in
 let AlwaysFalse = EqualsTo false in
diff --git a/examples/simple-contracts/simple-contract-div.ncl b/examples/simple-contracts/simple-contract-div.ncl
index 8e33eef5..0e0ed165 100644
--- a/examples/simple-contracts/simple-contract-div.ncl
+++ b/examples/simple-contracts/simple-contract-div.ncl
@@ -2,15 +2,15 @@
 // Illustrate a basic contract violation.
 
 let Even = fun label value =>
-  if builtins.is_num value && value % 2 == 0 then
+  if builtin.is_num value && value % 2 == 0 then
     value
   else
-    contracts.blame label in
+    contract.blame label in
 let DivBy3 = fun label value =>
-  if builtins.is_num value && value % 3 == 0 then
+  if builtin.is_num value && value % 3 == 0 then
     value
   else
-    contracts.blame label in
+    contract.blame label in
 // Will cause an error! 4 is no divided by 3.
 (4 | Even
    | DivBy3)
diff --git a/src/program.rs b/src/program.rs
index 7dd5f74a..ef008caf 100644
--- a/src/program.rs
+++ b/src/program.rs
@@ -193,7 +193,7 @@ where
 {
     let writer = StandardStream::stderr(ColorChoice::Always);
     let config = codespan_reporting::term::Config::default();
-    let contracts_id = cache.id_of("<stdlib/contracts.ncl>");
+    let contracts_id = cache.id_of("<stdlib/contract.ncl>");
     let diagnostics = error.to_diagnostic(cache.files_mut(), contracts_id);
 
     let result = diagnostics.iter().try_for_each(|d| {
diff --git a/src/repl/wasm_frontend.rs b/src/repl/wasm_frontend.rs
index ecb5a72e..5dc3a9b6 100644
--- a/src/repl/wasm_frontend.rs
+++ b/src/repl/wasm_frontend.rs
@@ -193,7 +193,7 @@ impl WasmInputResult {
     fn error(cache: &mut Cache, error: InputError) -> Self {
         let (msg, errors) = match error {
             InputError::NickelError(err) => {
-                let contracts_id = cache.id_of("<stdlib/contracts.ncl>");
+                let contracts_id = cache.id_of("<stdlib/contract.ncl>");
                 let diagnostics = err.to_diagnostic(cache.files_mut(), contracts_id);
 
                 let msg = diags_to_string(cache, &diagnostics);
@@ -289,7 +289,7 @@ pub fn diags_to_string(cache: &mut Cache, diags: &Vec<Diagnostic<FileId>>) -> St
 pub fn err_to_string(cache: &mut Cache, error: &InputError) -> String {
     match error {
         InputError::NickelError(nickel_err) => {
-            let contracts_id = cache.id_of("<stdlib/contracts.ncl>");
+            let contracts_id = cache.id_of("<stdlib/contract.ncl>");
             let diags = nickel_err.to_diagnostic(cache.files_mut(), contracts_id);
             diags_to_string(cache, &diags)
         }
diff --git a/src/serialize.rs b/src/serialize.rs
index 25e4386e..48fe291b 100644
--- a/src/serialize.rs
+++ b/src/serialize.rs
@@ -345,7 +345,7 @@ mod tests {
             json!(["a", "bc", "def", "g"])
         );
         assert_json_eq!(
-            r#"lists.fold (fun elt acc => [[elt]] @ acc) [] [1, 2, 3, 4]"#,
+            r#"list.fold (fun elt acc => [[elt]] @ acc) [] [1, 2, 3, 4]"#,
             json!([[1], [2], [3], [4]])
         );
         assert_json_eq!("[\"a\", 1, false, `foo]", json!(["a", 1, false, "foo"]));
diff --git a/src/stdlib.rs b/src/stdlib.rs
index 86064faf..bc24025f 100644
--- a/src/stdlib.rs
+++ b/src/stdlib.rs
@@ -3,32 +3,27 @@
 use crate::term::make as mk_term;
 use crate::term::RichTerm;
 
-pub const BUILTINS: (&str, &str) = (
-    "<stdlib/builtins.ncl>",
-    include_str!("../stdlib/builtins.ncl"),
+pub const BUILTIN: (&str, &str) = (
+    "<stdlib/builtin.ncl>",
+    include_str!("../stdlib/builtin.ncl"),
 );
-pub const CONTRACTS: (&str, &str) = (
-    "<stdlib/contracts.ncl>",
-    include_str!("../stdlib/contracts.ncl"),
-);
-pub const LISTS: (&str, &str) = ("<stdlib/lists>", include_str!("../stdlib/lists.ncl"));
-pub const RECORDS: (&str, &str) = ("<stdlib/records>", include_str!("../stdlib/records.ncl"));
-pub const STRINGS: (&str, &str) = ("<stdlib/strings>", include_str!("../stdlib/strings.ncl"));
-pub const NUMS: (&str, &str) = ("<stdlib/nums>", include_str!("../stdlib/nums.ncl"));
-pub const FUNCTIONS: (&str, &str) = (
-    "<stdlib/functions>",
-    include_str!("../stdlib/functions.ncl"),
+pub const CONTRACT: (&str, &str) = (
+    "<stdlib/contract.ncl>",
+    include_str!("../stdlib/contract.ncl"),
 );
+pub const LIST: (&str, &str) = ("<stdlib/list>", include_str!("../stdlib/list.ncl"));
+pub const RECORD: (&str, &str) = ("<stdlib/record>", include_str!("../stdlib/record.ncl"));
+pub const STRING: (&str, &str) = ("<stdlib/string>", include_str!("../stdlib/string.ncl"));
+pub const NUM: (&str, &str) = ("<stdlib/num>", include_str!("../stdlib/num.ncl"));
+pub const FUNCTION: (&str, &str) = ("<stdlib/function>", include_str!("../stdlib/function.ncl"));
 
 /// Return the list `(name, source_code)` of all the stdlib modules.
 pub fn modules() -> Vec<(&'static str, &'static str)> {
-    vec![
-        BUILTINS, CONTRACTS, LISTS, RECORDS, STRINGS, NUMS, FUNCTIONS,
-    ]
+    vec![BUILTIN, CONTRACT, LIST, RECORD, STRING, NUM, FUNCTION]
 }
 
 /// Accessors to the builtin contracts.
-pub mod contracts {
+pub mod contract {
     use super::*;
 
     macro_rules! generate_accessor {
diff --git a/src/types.rs b/src/types.rs
index 99014929..d65d8b8f 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -201,7 +201,7 @@ impl Types {
         pol: bool,
         sy: &mut i32,
     ) -> Result<RichTerm, UnboundTypeVariableError> {
-        use crate::stdlib::contracts;
+        use crate::stdlib::contract;
 
         fn get_var(
             vars: &HashMap<Ident, (RichTerm, RichTerm)>,
@@ -219,38 +219,38 @@ impl Types {
         }
 
         let ctr = match self.0 {
-            AbsType::Dyn() => contracts::dynamic(),
-            AbsType::Num() => contracts::num(),
-            AbsType::Bool() => contracts::bool(),
-            AbsType::Str() => contracts::string(),
+            AbsType::Dyn() => contract::dynamic(),
+            AbsType::Num() => contract::num(),
+            AbsType::Bool() => contract::bool(),
+            AbsType::Str() => contract::string(),
             //TODO: optimization: have a specialized contract for `List Dyn`, to avoid mapping an
             //always successful contract on each element.
-            AbsType::List(ref ty) => mk_app!(contracts::list(), ty.subcontract(h, pol, sy)?),
+            AbsType::List(ref ty) => mk_app!(contract::list(), ty.subcontract(h, pol, sy)?),
             AbsType::Sym() => panic!("Are you trying to check a Sym at runtime?"),
             AbsType::Arrow(ref s, ref t) => mk_app!(
-                contracts::func(),
+                contract::func(),
                 s.subcontract(h.clone(), !pol, sy)?,
                 t.subcontract(h, pol, sy)?
             ),
             AbsType::Flat(ref t) => t.clone(),
             AbsType::Var(ref id) => get_var(&h, id, true)?,
             AbsType::Forall(ref i, ref t) => {
-                let inst_var = mk_app!(contracts::forall_var(), Term::Sym(*sy), Term::Bool(pol));
+                let inst_var = mk_app!(contract::forall_var(), Term::Sym(*sy), Term::Bool(pol));
 
-                let inst_tail = mk_app!(contracts::forall_tail(), Term::Sym(*sy), Term::Bool(pol));
+                let inst_tail = mk_app!(contract::forall_tail(), Term::Sym(*sy), Term::Bool(pol));
 
                 h.insert(i.clone(), (inst_var, inst_tail));
                 *sy += 1;
                 t.subcontract(h, pol, sy)?
             }
-            AbsType::RowEmpty() | AbsType::RowExtend(..) => contracts::fail(),
+            AbsType::RowEmpty() | AbsType::RowExtend(..) => contract::fail(),
             AbsType::Enum(ref r) => {
                 fn form(
                     ty: Types,
                     h: HashMap<Ident, (RichTerm, RichTerm)>,
                 ) -> Result<RichTerm, UnboundTypeVariableError> {
                     let ctr = match ty.0 {
-                        AbsType::RowEmpty() => contracts::fail(),
+                        AbsType::RowEmpty() => contract::fail(),
                         AbsType::RowExtend(_, Some(_), _) => {
                             panic!("It should be a row without type")
                         }
@@ -260,7 +260,7 @@ impl Types {
                             map.insert(id, Term::Bool(true).into());
 
                             mk_app!(
-                                contracts::row_extend(),
+                                contract::row_extend(),
                                 rest_contract,
                                 mk_fun!(
                                     "x",
@@ -289,14 +289,14 @@ impl Types {
                     h: HashMap<Ident, (RichTerm, RichTerm)>,
                 ) -> Result<RichTerm, UnboundTypeVariableError> {
                     let ctr = match &ty.0 {
-                        AbsType::RowEmpty() => contracts::empty_tail(),
-                        AbsType::Dyn() => contracts::dyn_tail(),
+                        AbsType::RowEmpty() => contract::empty_tail(),
+                        AbsType::Dyn() => contract::dyn_tail(),
                         AbsType::Var(id) => get_var(&h, id, false)?,
                         AbsType::RowExtend(id, Some(ty), rest) => {
                             let cont = form(sy, pol, rest.as_ref(), h.clone())?;
                             let row_contr = ty.subcontract(h, pol, sy)?;
                             mk_app!(
-                                contracts::record_extend(),
+                                contract::record_extend(),
                                 mk_term::string(format!("{}", id)),
                                 row_contr,
                                 cont
@@ -311,10 +311,10 @@ impl Types {
                     Ok(ctr)
                 }
 
-                mk_app!(contracts::record(), form(sy, pol, ty, h)?)
+                mk_app!(contract::record(), form(sy, pol, ty, h)?)
             }
             AbsType::DynRecord(ref ty) => {
-                mk_app!(contracts::dyn_record(), ty.subcontract(h, pol, sy)?)
+                mk_app!(contract::dyn_record(), ty.subcontract(h, pol, sy)?)
             }
         };
 
diff --git a/stdlib/builtins.ncl b/stdlib/builtin.ncl
similarity index 99%
rename from stdlib/builtins.ncl
rename to stdlib/builtin.ncl
index 115cdb8a..4b4d9d33 100644
--- a/stdlib/builtins.ncl
+++ b/stdlib/builtin.ncl
@@ -1,5 +1,5 @@
 {
-  builtins = {
+  builtin = {
     is_num : Dyn -> Bool
     | doc m#"
       Checks if the given value is a number.
diff --git a/stdlib/contracts.ncl b/stdlib/contract.ncl
similarity index 99%
rename from stdlib/contracts.ncl
rename to stdlib/contract.ncl
index ffcf2e73..7ba1758f 100644
--- a/stdlib/contracts.ncl
+++ b/stdlib/contract.ncl
@@ -75,7 +75,7 @@
       if t == {} then acc
       else %blame% (%tag% "extra field `#{%head% (%fields% t)}`" l),
 
-  contracts = {
+  contract = {
     blame
       | doc m#"
         Raise blame for a given label.
diff --git a/stdlib/functions.ncl b/stdlib/function.ncl
similarity index 92%
rename from stdlib/functions.ncl
rename to stdlib/function.ncl
index 42317b0a..886406a9 100644
--- a/stdlib/functions.ncl
+++ b/stdlib/function.ncl
@@ -1,5 +1,5 @@
 {
-  functions = {
+  function = {
     id : forall a. a -> a
     | doc "The identity function"
     = fun x => x,
diff --git a/stdlib/lists.ncl b/stdlib/list.ncl
similarity index 99%
rename from stdlib/lists.ncl
rename to stdlib/list.ncl
index 12262326..4852f789 100644
--- a/stdlib/lists.ncl
+++ b/stdlib/list.ncl
@@ -1,5 +1,5 @@
 {
-  lists = {
+  list = {
     NonEmpty
       | doc m#"
         Contract to ensure the given list is not empty.
diff --git a/stdlib/nums.ncl b/stdlib/num.ncl
similarity index 99%
rename from stdlib/nums.ncl
rename to stdlib/num.ncl
index a372efa0..db712b3b 100644
--- a/stdlib/nums.ncl
+++ b/stdlib/num.ncl
@@ -1,5 +1,5 @@
 {
-  nums = {
+  num = {
     Int
     | doc m#"
       Contract to enforce a number is an integer.
diff --git a/stdlib/records.ncl b/stdlib/record.ncl
similarity index 98%
rename from stdlib/records.ncl
rename to stdlib/record.ncl
index dac0ad86..f5cf36a6 100644
--- a/stdlib/records.ncl
+++ b/stdlib/record.ncl
@@ -1,5 +1,5 @@
 {
-  records = {
+  record = {
     map : forall a b. (Str -> a -> b) -> {_: a} -> {_: b}
     | doc m#"
       Maps a function on every field of a record. The string argument of the function argument is the name of the
diff --git a/stdlib/strings.ncl b/stdlib/string.ncl
similarity index 99%
rename from stdlib/strings.ncl
rename to stdlib/string.ncl
index 0a539ba8..5f791c37 100644
--- a/stdlib/strings.ncl
+++ b/stdlib/string.ncl
@@ -1,5 +1,5 @@
 {
-  strings = {
+  string = {
     BoolLiteral
     | doc m#"
       Contract to enforce the value is a string that represents a boolean literal. Additionally casts "True" to "true"
@@ -135,7 +135,7 @@
       if %length% l == 0 then
         ""
       else
-        %head% l ++ lists.foldl (fun acc s => acc ++ sep ++ s) "" (%tail% l),
+        %head% l ++ list.foldl (fun acc s => acc ++ sep ++ s) "" (%tail% l),
 
     split : Str -> Str -> List Str
     | doc m#"


Test patch:
diff --git a/tests/imports.rs b/tests/imports.rs
index 34a2ba70..1e065a26 100644
--- a/tests/imports.rs
+++ b/tests/imports.rs
@@ -89,7 +89,7 @@ fn serialize() {
     let mut prog = Program::new_from_source(
         BufReader::new(
             format!(
-                "(builtins.serialize `Json ({})) == (builtins.serialize `Json ({{foo = \"ab\"}}))",
+                "(builtin.serialize `Json ({})) == (builtin.serialize `Json ({{foo = \"ab\"}}))",
                 mk_import("record.ncl")
             )
             .as_bytes(),
diff --git a/tests/pass/annotations.ncl b/tests/pass/annotations.ncl
index 81a6aa2e..3d68bae5 100644
--- a/tests/pass/annotations.ncl
+++ b/tests/pass/annotations.ncl
@@ -24,4 +24,4 @@ let Assert = fun l x => x || %blame% l in
   (let AssertOk = fun l t => if t == `Ok then t else %blame% l in
     switch {`Ok => true, `Err => false} `Ok | AssertOk),
 ]
-|> lists.foldl (fun x y => x && y) true
+|> list.foldl (fun x y => x && y) true
diff --git a/tests/pass/basics.ncl b/tests/pass/basics.ncl
index 593590c3..1faa37d5 100644
--- a/tests/pass/basics.ncl
+++ b/tests/pass/basics.ncl
@@ -34,4 +34,4 @@ let Assert = fun l x => x || %blame% l in
   // This test checks that the terms of a switch are closured
   let x = 3 in (switch { `foo => 1, _ => x} (3 + 2)) == 3,
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/builtins.ncl b/tests/pass/builtins.ncl
index c005ea70..20239e92 100644
--- a/tests/pass/builtins.ncl
+++ b/tests/pass/builtins.ncl
@@ -2,7 +2,7 @@ let Assert = fun l x => x || %blame% l in
 
 [
   // is_record
-  builtins.is_record {},
+  builtin.is_record {},
 
   /// This currently do not check that subexpressions are actually forced,
   /// just that the evaluation succeeds
@@ -21,10 +21,10 @@ let Assert = fun l x => x || %blame% l in
     %deep_seq% r (r.a.b) == 3,
 
   [1,2,3]
-   |> lists.map (fun x => x + 1)
-   |> lists.filter (fun x => x > 2)
-   |> builtins.serialize `Json
-   |> builtins.deserialize `Json
+   |> list.map (fun x => x + 1)
+   |> list.filter (fun x => x > 2)
+   |> builtin.serialize `Json
+   |> builtin.deserialize `Json
    == [3,4],
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/contracts.ncl b/tests/pass/contracts.ncl
index 1006a487..487b06eb 100644
--- a/tests/pass/contracts.ncl
+++ b/tests/pass/contracts.ncl
@@ -121,15 +121,15 @@ let Assert = fun l x => x || %blame% l in
   (f {foo = 1}).bar == 1,
   // user-written contract application
   let Extend = fun base label value =>
-    let derived = if builtins.is_record base then
+    let derived = if builtin.is_record base then
       (base & {foo | Num})
     else
       base in
-    contracts.apply derived label value in
+    contract.apply derived label value in
   let Contract = Extend {bar | Num, ..} in
   let Id = Extend (fun label value => value) in
   ({bar = 1, foo = 1} | Contract)
     & ({baz = 1} | Id)
    == {foo = 1, bar = 1, baz = 1},
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/eq.ncl b/tests/pass/eq.ncl
index 2ad1dcd3..61514d70 100644
--- a/tests/pass/eq.ncl
+++ b/tests/pass/eq.ncl
@@ -25,7 +25,7 @@ let Assert = fun l x => x || %blame% l in
     == [1, "ab", true],
   [[[]]] == [[[]]],
   [[1], [[2]]] == [[2 + (-1)], [[1 + 1]]],
-  [[true, false]] == lists.flatten [[[true, false]]],
+  [[true, false]] == list.flatten [[[true, false]]],
 
   [] != [1],
   [] != 1,
@@ -75,4 +75,4 @@ let Assert = fun l x => x || %blame% l in
       == false
   ),
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/functions.ncl b/tests/pass/functions.ncl
index 30f67b40..161c8577 100644
--- a/tests/pass/functions.ncl
+++ b/tests/pass/functions.ncl
@@ -15,4 +15,4 @@ let Assert = fun l x => x || %blame% l in
     g true
     == 4,
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/lists.ncl b/tests/pass/lists.ncl
index cfb3efdf..9586513f 100644
--- a/tests/pass/lists.ncl
+++ b/tests/pass/lists.ncl
@@ -2,13 +2,13 @@ let Assert = fun l x => x || %blame% l in
 
 [
   // accesses
-  lists.elem_at 1 [1,2,3] == 2,
-  lists.elem_at 1 (lists.map (fun x => x + 1) [1,2,3]) == 3,
+  list.elem_at 1 [1,2,3] == 2,
+  list.elem_at 1 (list.map (fun x => x + 1) [1,2,3]) == 3,
 
   // length
-  lists.length [] == 0,
-  lists.length [1,2,3] == 3,
-  lists.length ([] @ [1,2] @ [3,4] @ []) == 4,
+  list.length [] == 0,
+  list.length [1,2,3] == 3,
+  list.length ([] @ [1,2] @ [3,4] @ []) == 4,
 
   // Test case added after https://github.com/tweag/nickel/issues/154
   let x = 1 in let l = [x] @ [2] in %head% l == 1,
@@ -33,4 +33,4 @@ let Assert = fun l x => x || %blame% l in
     let isZ = fun x => x == 0 in
     all isZ [0, 0, 0, 1] == false,
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/metavalues.ncl b/tests/pass/metavalues.ncl
index 89ceda18..7da70048 100644
--- a/tests/pass/metavalues.ncl
+++ b/tests/pass/metavalues.ncl
@@ -6,7 +6,7 @@ let Assert = fun l x => x || %blame% l in
   // Check the correct handling of the update of thunks containing enriched values (see issue
   // https://github.com/tweag/nickel/issues/123)
   let x = {a = (fun x => (1 | default)) 1} in
-    builtins.seq (x.a) ((x & {a=2}).a) == 2,
+    builtin.seq (x.a) ((x & {a=2}).a) == 2,
 
   // merge_default
   ({a = 2} & {a | default = 0, b | default = true}) == {a = 2, b = true},
@@ -53,4 +53,4 @@ let Assert = fun l x => x || %blame% l in
   // value/contract-default <- contract/contract-default
   ((val & (ctr_num & def)).a == 1 | Assert)),
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/overriding.ncl b/tests/pass/overriding.ncl
index c0515472..147dfb30 100644
--- a/tests/pass/overriding.ncl
+++ b/tests/pass/overriding.ncl
@@ -1,17 +1,17 @@
-let Assert = contracts.from_predicate functions.id in
+let Assert = contract.from_predicate function.id in
 
 [
   {foo | default = 1} & {foo = 2} == {foo = 2},
   {foo = 1 + 1, bar = foo + 1} == {foo = 2, bar = 3},
 
   let r = {foo | default = 1 + 1, bar = foo + 1} in
-  builtins.deep_seq (r & {foo = 3}) r == {foo = 2, bar = 3},
+  builtin.deep_seq (r & {foo = 3}) r == {foo = 2, bar = 3},
 
   let r = {foo | default = 1 + 1, bar = foo + 1} in
   (r & {foo = 3}) == {foo = 3, bar = 4},
 
   let r = {foo | default = 1 + 1, bar = foo + 1} in
-  builtins.deep_seq r (r & {foo = 3}) == {foo = 3, bar = 4},
+  builtin.deep_seq r (r & {foo = 3}) == {foo = 3, bar = 4},
 
   let ext = 0 + 1 in
   let r = {
@@ -20,7 +20,7 @@ let Assert = contracts.from_predicate functions.id in
     b = let inner = 1 in a + ext + inner,
     c = let inner = 2 in b + ext + inner,
   } in
-  builtins.deep_seq (r & {foo = 1 - 1}) r
+  builtin.deep_seq (r & {foo = 1 - 1}) r
     == {foo = 2, a = 3, b = 5, c = 8},
 
   let ext = 0 + 1 in
@@ -30,7 +30,7 @@ let Assert = contracts.from_predicate functions.id in
     b = let inner = 1 in a + ext + inner,
     c = let inner = 2 in b + ext + inner,
   } in
-  builtins.deep_seq r (r & {foo = 1 - 1})
+  builtin.deep_seq r (r & {foo = 1 - 1})
     == {foo = 0, a = 1, b = 3, c = 6},
 
   let nested = {
@@ -40,7 +40,7 @@ let Assert = contracts.from_predicate functions.id in
       other = stuff + 1,
     },
   } in
-  builtins.deep_seq (nested & {foo.bar.baz = 1}) nested
+  builtin.deep_seq (nested & {foo.bar.baz = 1}) nested
     == {foo.bar.baz = 0, some.nested.stuff = 1, some.nested.other = 2},
 
   let nested = {
@@ -50,7 +50,7 @@ let Assert = contracts.from_predicate functions.id in
       other = stuff + 1,
     },
   } in
-  builtins.deep_seq nested (nested & {foo.bar.baz = 1})
+  builtin.deep_seq nested (nested & {foo.bar.baz = 1})
     == {foo.bar.baz = 1, some.nested.stuff = 2, some.nested.other = 3},
 
   let base = {foo | default = "a", bar = foo ++ "b"} in
@@ -59,9 +59,9 @@ let Assert = contracts.from_predicate functions.id in
   (base.bar == "ab"
   && ext1.bar == "1b"
   && ext2.bar == "Ab")
-  |> builtins.deep_seq base
-  |> builtins.deep_seq ext1
-  |> builtins.deep_seq ext2,
+  |> builtin.deep_seq base
+  |> builtin.deep_seq ext1
+  |> builtin.deep_seq ext2,
 
   // Test that the evaluation of a recursive record patches the right
   // environment in some edge cases (when fields only contains a variable)
@@ -71,4 +71,4 @@ let Assert = contracts.from_predicate functions.id in
   ({foo | default = 1, bar = foo} & {foo = 2}).bar == 2,
   ({foo | default = 1, bar = foo, baz = bar} & {foo = 2}).baz == 2,
 ]
-|> lists.foldl (fun next acc => (next | Assert) && acc) true
+|> list.foldl (fun next acc => (next | Assert) && acc) true
diff --git a/tests/pass/record-defs.ncl b/tests/pass/record-defs.ncl
index 443a6e89..7773db04 100644
--- a/tests/pass/record-defs.ncl
+++ b/tests/pass/record-defs.ncl
@@ -40,4 +40,4 @@ let Assert = fun l x => x || %blame% l in
   let x = "foo" in {"#{x}" = bar, bar = 1} == {foo = 1, bar = 1},
   ({"#foo"."#bar".baz = other + 1, other = 0}."#foo"."#bar".baz == 1),
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/records.ncl b/tests/pass/records.ncl
index 837670d6..6040a845 100644
--- a/tests/pass/records.ncl
+++ b/tests/pass/records.ncl
@@ -13,18 +13,18 @@ let Assert = fun l x => x || %blame% l in
   ({bar = 3}$["foo" = true]).foo == true,
 
   // primitive_ops
-  records.has_field "foo" {foo = 1, bar = 2},
-  records.has_field "fop" {foo = 1, bar = 2} == false,
-  records.has_field "foo" ({foo = 2, bar = 3} -$ "foo")
+  record.has_field "foo" {foo = 1, bar = 2},
+  record.has_field "fop" {foo = 1, bar = 2} == false,
+  record.has_field "foo" ({foo = 2, bar = 3} -$ "foo")
     == false,
 
-  records.has_field "foo" ({bar = 3}$["foo" = 1]),
+  record.has_field "foo" ({bar = 3}$["foo" = 1]),
 
   // lazyness of map
-  (records.map (fun x y => y + 1) {foo = 1, bar = "it's lazy"}).foo
+  (record.map (fun x y => y + 1) {foo = 1, bar = "it's lazy"}).foo
     == 2,
 
-  let r = records.map
+  let r = record.map
       (fun y x => if %is_num% x then x + 1 else 0)
       {foo = 1, bar = "it's lazy"} in
     (r.foo) + (r.bar) == 2,
@@ -101,7 +101,7 @@ let Assert = fun l x => x || %blame% l in
   // regression tests for [#579](https://github.com/tweag/nickel/issues/579)
   // and [#583](https://github.com/tweag/nickel/issues/583)
   ({foo.bar = foo.baz, foo.baz | default = 2} & {foo.baz = 1}).foo.bar == 1,
-  let Name = fun b label name => if b then "hijack" else contracts.blame label in
+  let Name = fun b label name => if b then "hijack" else contract.blame label in
   let Config = {
       b | Bool,
       name | Name b,
@@ -112,4 +112,4 @@ let Assert = fun l x => x || %blame% l in
   } in
   data.name == "hijack",
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/serialize-package.ncl b/tests/pass/serialize-package.ncl
index 1f59153c..9a7fcefb 100644
--- a/tests/pass/serialize-package.ncl
+++ b/tests/pass/serialize-package.ncl
@@ -53,12 +53,12 @@ let ctr = {
           = "package",
   }
 } in
-builtins.serialize `Json (
+builtin.serialize `Json (
   {
     name = "nickel",
     buildInputs = [{package = "hello"}],
   } | ctr.Shell
-) == builtins.serialize `Json {
+) == builtin.serialize `Json {
   name = "nickel",
   buildInputs = [{input = "nixpkgs", package = "hello", "_type" = "package"}],
 }
diff --git a/tests/pass/serialize.ncl b/tests/pass/serialize.ncl
index 1c8340d5..d7fe862d 100644
--- a/tests/pass/serialize.ncl
+++ b/tests/pass/serialize.ncl
@@ -29,4 +29,4 @@ let assertDeserInv = fun x =>
       baz = {subfoo = true, subbar = 0}
     },
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/strings.ncl b/tests/pass/strings.ncl
index 52db2961..42296ccb 100644
--- a/tests/pass/strings.ncl
+++ b/tests/pass/strings.ncl
@@ -21,4 +21,4 @@ let Assert = fun l x => x || %blame% l in
   let s = "Hello" in m##""###{s}" World"##m == "\"#Hello\" World",
   m##""##s"##m == "\"##s",
 ]
-|> lists.foldl (fun x y => (x | Assert) && y) true
+|> list.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/typechecking.ncl b/tests/pass/typechecking.ncl
index 8ae8353f..6d10de5e 100644
--- a/tests/pass/typechecking.ncl
+++ b/tests/pass/typechecking.ncl
@@ -176,13 +176,13 @@ let typecheck = [
   {"foo" = 1} : {foo : Num},
 
   // stdlib typechecking:
-  strings.length : Str -> Num,
-  (strings.length "Ok") : Num,
-  (strings.length "Ok" == 2) : Bool,
+  string.length : Str -> Num,
+  (string.length "Ok") : Num,
+  (string.length "Ok" == 2) : Bool,
   // partial application
-  (strings.split ".") : Str -> List Str,
-  (lists.length [] == 0) : Bool,
-  (lists.map (fun x => x ++ "1") ["a", "b", "c"]) : List Str,
+  (string.split ".") : Str -> List Str,
+  (list.length [] == 0) : Bool,
+  (list.map (fun x => x ++ "1") ["a", "b", "c"]) : List Str,
 ] in
 
 true
diff --git a/tests/query.rs b/tests/query.rs
index fbdec93e..cab9b346 100644
--- a/tests/query.rs
+++ b/tests/query.rs
@@ -18,7 +18,7 @@ pub fn test_query_metadata_basic() {
 #[test]
 pub fn test_query_metadata_from_func() {
     let mut program = Program::new_from_source(
-        "builtins.seq 2 ((3+1) | doc \"Test from func\")".as_bytes(),
+        "builtin.seq 2 ((3+1) | doc \"Test from func\")".as_bytes(),
         "regr_tests",
     )
     .unwrap();
diff --git a/tests/stdlib_lists_fail.rs b/tests/stdlib_lists_fail.rs
index adfd038c..56ddf870 100644
--- a/tests/stdlib_lists_fail.rs
+++ b/tests/stdlib_lists_fail.rs
@@ -27,11 +27,11 @@ fn elem_at() {
     );
 
     assert_matches!(
-        eval("lists.elem_at 0 {} 0"),
+        eval("list.elem_at 0 {} 0"),
         Err(Error::EvalError(EvalError::BlameError(..)))
     );
     assert_matches!(
-        eval("lists.elem_at \"a\" []"),
+        eval("list.elem_at \"a\" []"),
         Err(Error::EvalError(EvalError::BlameError(..)))
     );
 }
@@ -55,21 +55,21 @@ fn head_tail() {
         Err(Error::EvalError(EvalError::TypeError(..)))
     );
 
-    // TODO: add non-empty contract to the input of lists.head and lists.tail
+    // TODO: add non-empty contract to the input of list.head and list.tail
     // assert_matches!(
-    //     eval("lists.head []"),
+    //     eval("list.head []"),
     //     Err(Error::EvalError(EvalError::BlameError(..)))
     // );
     // assert_matches!(
-    //     eval("lists.tail []"),
+    //     eval("list.tail []"),
     //     Err(Error::EvalError(EvalError::BlameError(..)))
     // );
     assert_matches!(
-        eval("lists.head false"),
+        eval("list.head false"),
         Err(Error::EvalError(EvalError::BlameError(..)))
     );
     assert_matches!(
-        eval("lists.tail 2"),
+        eval("list.tail 2"),
         Err(Error::EvalError(EvalError::BlameError(..)))
     );
 }
diff --git a/tests/unbound_type_variables.rs b/tests/unbound_type_variables.rs
index 13d8ee78..16faf69b 100644
--- a/tests/unbound_type_variables.rs
+++ b/tests/unbound_type_variables.rs
@@ -53,7 +53,7 @@ fn unbound_type_variables() {
     );
     assert_unbound!(
         "let f | a -> (forall a. a -> a)
-                       = fun x => builtins.seq x null in
+                       = fun x => builtin.seq x null in
                        f null",
         "a"
     );