From 73b9dd479d69b58242130290722b31a3ed4dbb31 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 21:30:00 +0200 Subject: [PATCH 1/7] Promote changes from 5.5 --- doc/docs/tutorials/provider-explicit/README.md | 12 ++++-------- .../tutorials/provider-explicit/provider_explicit.ml | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/doc/docs/tutorials/provider-explicit/README.md b/doc/docs/tutorials/provider-explicit/README.md index 4bc8b97..bcea898 100644 --- a/doc/docs/tutorials/provider-explicit/README.md +++ b/doc/docs/tutorials/provider-explicit/README.md @@ -20,12 +20,8 @@ let id (module A : Id) (x : A.t) = A.id x ;; ``` ```ansi -Line 7, characters 23-32: -7 | let id (module A : Id) (x : A.t) = A.id x ;; - ^^^^^^^^^ -Error: This pattern matches values of type A.t - but a pattern was expected which matches values of type 'a - The type constructor A.t would escape its scope +module type Id = sig type t val id : t -> t end +val id : (module A : Id) -> A.t -> A.t = ``` As you can see above, constructs of these kinds are currently not in the @@ -306,9 +302,9 @@ end) ``` ```ansi -Line 2, characters 14-15: +Line 2, characters 16-17: 2 | val t : ('a 't, (module Mappable with type 'a t = 'a 't), [> mappable ]) Provider.Trait.t - ^ + ^ Error: Syntax error ``` diff --git a/doc/docs/tutorials/provider-explicit/provider_explicit.ml b/doc/docs/tutorials/provider-explicit/provider_explicit.ml index 605af31..e64be42 100644 --- a/doc/docs/tutorials/provider-explicit/provider_explicit.ml +++ b/doc/docs/tutorials/provider-explicit/provider_explicit.ml @@ -44,12 +44,8 @@ let id (module A : Id) (x : A.t) = A.id x ;; ``` ```ansi - Line 7, characters 23-32: - 7 | let id (module A : Id) (x : A.t) = A.id x ;; - ^^^^^^^^^ - Error: This pattern matches values of type A.t - but a pattern was expected which matches values of type 'a - The type constructor A.t would escape its scope + module type Id = sig type t val id : t -> t end + val id : (module A : Id) -> A.t -> A.t = ``` |}]; () @@ -399,9 +395,9 @@ end) ``` ```ansi - Line 2, characters 14-15: + Line 2, characters 16-17: 2 | val t : ('a 't, (module Mappable with type 'a t = 'a 't), [> mappable ]) Provider.Trait.t - ^ + ^ Error: Syntax error ``` |}]; From aa073727be212aa06d85f7da387d14707d79c7d1 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 21:44:24 +0200 Subject: [PATCH 2/7] Update text around modular explicit being available now --- .../tutorials/provider-explicit/README.md | 14 +++----- .../provider-explicit/provider_explicit.ml | 36 +++++++++---------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/doc/docs/tutorials/provider-explicit/README.md b/doc/docs/tutorials/provider-explicit/README.md index bcea898..4d70844 100644 --- a/doc/docs/tutorials/provider-explicit/README.md +++ b/doc/docs/tutorials/provider-explicit/README.md @@ -24,9 +24,7 @@ module type Id = sig type t val id : t -> t end val id : (module A : Id) -> A.t -> A.t = ``` -As you can see above, constructs of these kinds are currently not in the -language, but they are introduced in the version `5.5` of OCaml. We'll make -sure to update that part of the doc when we migrate to these new features! +Constructs of these kinds were introduced in the version `5.5` of OCaml. Back to our tutorial: we titled it *provider-explicit* in reference to this. In the pattern we present here, functions take an additional *provider* @@ -244,7 +242,7 @@ interface working on a parametrized type, a concept known as Consider values that can be mapped: ```ocaml -module type Mappable = sig +module type Mappable0 = sig type 'a t val map : 'a t -> f:('a -> 'b) -> 'b t @@ -254,15 +252,13 @@ end Imagine you want to write a function that applies the same mapping function multiple times for some reason. -This kind of higher-kinded polymorphism will be achievable using modular -explicit. It might look something like this in the future: +This kind of higher-kinded polymorphism is achievable using modular explicit: ```ocaml -let map_n_times (type a) (module A : Mappable) (x : a A.t) ~(f : a -> a) ~n = - let rec loop n x = if n = 0 then x else loop (n - 1) (A.map f x) in +let _map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = + let rec loop n x = if Int.equal n 0 then x else loop (n - 1) (A.map x ~f) in loop n x ;; -val map_n_times : (module A : Mappable) -> 'a A.t -> f:('a -> 'a) -> n:int -> 'a = ``` In this section we show how to do this with the *provider* library, leveraging diff --git a/doc/docs/tutorials/provider-explicit/provider_explicit.ml b/doc/docs/tutorials/provider-explicit/provider_explicit.ml index e64be42..ca9611d 100644 --- a/doc/docs/tutorials/provider-explicit/provider_explicit.ml +++ b/doc/docs/tutorials/provider-explicit/provider_explicit.ml @@ -53,9 +53,7 @@ let id (module A : Id) (x : A.t) = A.id x ;; (* @mdexp - As you can see above, constructs of these kinds are currently not in the - language, but they are introduced in the version `5.5` of OCaml. We'll make - sure to update that part of the doc when we migrate to these new features! + Constructs of these kinds were introduced in the version `5.5` of OCaml. Back to our tutorial: we titled it *provider-explicit* in reference to this. In the pattern we present here, functions take an additional *provider* @@ -320,27 +318,29 @@ let%expect_test "double_then_repeat" = Consider values that can be mapped: - ```ocaml - module type Mappable = sig - type 'a t + @mdexp.code *) + +module type Mappable0 = sig + type 'a t - val map : 'a t -> f:('a -> 'b) -> 'b t - end - ``` + val map : 'a t -> f:('a -> 'b) -> 'b t +end + +(* @mdexp Imagine you want to write a function that applies the same mapping function multiple times for some reason. - This kind of higher-kinded polymorphism will be achievable using modular - explicit. It might look something like this in the future: + This kind of higher-kinded polymorphism is achievable using modular explicit: *) + +(* @mdexp.code *) - ```ocaml - let map_n_times (type a) (module A : Mappable) (x : a A.t) ~(f : a -> a) ~n = - let rec loop n x = if n = 0 then x else loop (n - 1) (A.map f x) in - loop n x - ;; - val map_n_times : (module A : Mappable) -> 'a A.t -> f:('a -> 'a) -> n:int -> 'a = - ``` +let _map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = + let rec loop n x = if Int.equal n 0 then x else loop (n - 1) (A.map x ~f) in + loop n x +;; + +(* @mdexp In this section we show how to do this with the *provider* library, leveraging the [higher_kinded](https://github.com/janestreet/higher_kinded) library. From 33ead49bf9087e388d1f95223668e713f4ce3410 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Tue, 11 Aug 2026 21:46:27 +0200 Subject: [PATCH 3/7] Simplify mdexp directives --- doc/docs/tutorials/provider-explicit/README.md | 1 - doc/docs/tutorials/provider-explicit/provider_explicit.ml | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/docs/tutorials/provider-explicit/README.md b/doc/docs/tutorials/provider-explicit/README.md index 4d70844..aa2fb70 100644 --- a/doc/docs/tutorials/provider-explicit/README.md +++ b/doc/docs/tutorials/provider-explicit/README.md @@ -168,7 +168,6 @@ module type Repeatable = sig end ``` - ```ocaml type repeatable = [ `Repeatable ] diff --git a/doc/docs/tutorials/provider-explicit/provider_explicit.ml b/doc/docs/tutorials/provider-explicit/provider_explicit.ml index ca9611d..6e9f249 100644 --- a/doc/docs/tutorials/provider-explicit/provider_explicit.ml +++ b/doc/docs/tutorials/provider-explicit/provider_explicit.ml @@ -232,9 +232,7 @@ module type Repeatable = sig val repeat : t -> t end -(* @mdexp.end *) - -(* @mdexp +(* @mdexp.end @mdexp.code *) @@ -331,9 +329,9 @@ end Imagine you want to write a function that applies the same mapping function multiple times for some reason. - This kind of higher-kinded polymorphism is achievable using modular explicit: *) + This kind of higher-kinded polymorphism is achievable using modular explicit: -(* @mdexp.code *) + @mdexp.code *) let _map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = let rec loop n x = if Int.equal n 0 then x else loop (n - 1) (A.map x ~f) in From 27ad37e7d2254701b658f48bb11ca8665158372f Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Wed, 12 Aug 2026 06:50:26 +0200 Subject: [PATCH 4/7] Now we must require 5.5 for the dev pkg --- dune-project | 2 +- provider-dev.opam | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dune-project b/dune-project index b5a0fa4..5be2209 100644 --- a/dune-project +++ b/dune-project @@ -72,7 +72,7 @@ (allow_empty) (depends (ocaml - (>= 5.3)) + (>= 5.5)) (ocamlformat (= 0.29.0)) (bisect_ppx diff --git a/provider-dev.opam b/provider-dev.opam index cdfb2d4..aa3ea7c 100644 --- a/provider-dev.opam +++ b/provider-dev.opam @@ -9,7 +9,7 @@ doc: "https://mbarbin.github.io/provider/" bug-reports: "https://github.com/mbarbin/provider/issues" depends: [ "dune" {>= "3.20"} - "ocaml" {>= "5.3"} + "ocaml" {>= "5.5"} "ocamlformat" {= "0.29.0"} "bisect_ppx" {>= "2.8.3"} "dyn" {>= "3.20"} From 9d6cd377691ee45d996c6fcc17e780157cda1504 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Wed, 12 Aug 2026 06:50:52 +0200 Subject: [PATCH 5/7] Use 5.5 in the main and doc CIs --- .github/workflows/ci.yml | 2 +- .github/workflows/deploy-doc.yml | 2 +- .github/workflows/test-deploy-doc.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10e65ea..f4786c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: os: - ubuntu-latest ocaml-compiler: - - 5.4.x + - 5.5.x runs-on: ${{ matrix.os }} diff --git a/.github/workflows/deploy-doc.yml b/.github/workflows/deploy-doc.yml index ff8c6fa..2fe3f4e 100644 --- a/.github/workflows/deploy-doc.yml +++ b/.github/workflows/deploy-doc.yml @@ -37,7 +37,7 @@ jobs: - name: Setup OCaml uses: ocaml/setup-ocaml@dec6499fef64fc5d7ed43d43a87251b7b1c306f5 # v3.4.8 with: - ocaml-compiler: "5.4.x" + ocaml-compiler: "5.5.x" dune-cache: true opam-repositories: | default: https://github.com/ocaml/opam-repository.git diff --git a/.github/workflows/test-deploy-doc.yml b/.github/workflows/test-deploy-doc.yml index 827406d..8354dcf 100644 --- a/.github/workflows/test-deploy-doc.yml +++ b/.github/workflows/test-deploy-doc.yml @@ -37,7 +37,7 @@ jobs: - name: Setup OCaml uses: ocaml/setup-ocaml@dec6499fef64fc5d7ed43d43a87251b7b1c306f5 # v3.4.8 with: - ocaml-compiler: "5.4.x" + ocaml-compiler: "5.5.x" dune-cache: true opam-repositories: | default: https://github.com/ocaml/opam-repository.git From a6a56be7cf52e3792311bcb6424a18c822fe42c3 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Wed, 12 Aug 2026 06:56:37 +0200 Subject: [PATCH 6/7] Add 5.5 to more CI and fix exclusion to main CI version --- .github/workflows/more-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/more-ci.yml b/.github/workflows/more-ci.yml index d18d525..4aaccdf 100644 --- a/.github/workflows/more-ci.yml +++ b/.github/workflows/more-ci.yml @@ -31,6 +31,7 @@ jobs: - macos-latest - ubuntu-latest ocaml-compiler: + - 5.5.x - 5.4.x - 5.3.x - 5.2.x @@ -38,7 +39,7 @@ jobs: exclude: # We exclude the combination already tested in the 'ci' workflow. - os: ubuntu-latest - ocaml-compiler: 5.4.x + ocaml-compiler: 5.5.x runs-on: ${{ matrix.os }} From f7cbf36f3c5ea0493825bf6283c522c205075101 Mon Sep 17 00:00:00 2001 From: Mathieu Barbin Date: Wed, 12 Aug 2026 07:09:02 +0200 Subject: [PATCH 7/7] Use map n times to illustrate and cover --- doc/docs/tutorials/provider-explicit/README.md | 10 +++++++++- .../tutorials/provider-explicit/provider_explicit.ml | 11 ++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/doc/docs/tutorials/provider-explicit/README.md b/doc/docs/tutorials/provider-explicit/README.md index aa2fb70..9259234 100644 --- a/doc/docs/tutorials/provider-explicit/README.md +++ b/doc/docs/tutorials/provider-explicit/README.md @@ -254,12 +254,20 @@ multiple times for some reason. This kind of higher-kinded polymorphism is achievable using modular explicit: ```ocaml -let _map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = +let map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = let rec loop n x = if Int.equal n 0 then x else loop (n - 1) (A.map x ~f) in loop n x ;; ``` +```ocaml +let%expect_test "map n times" = + let result = map_n_times (module List) [ 0; 1; 2 ] ~f:Int.succ ~n:10 in + print_dyn (result |> Dyn.list Dyn.int); + [%expect {| [ 10; 11; 12 ] |}] +;; +``` + In this section we show how to do this with the *provider* library, leveraging the [higher_kinded](https://github.com/janestreet/higher_kinded) library. diff --git a/doc/docs/tutorials/provider-explicit/provider_explicit.ml b/doc/docs/tutorials/provider-explicit/provider_explicit.ml index 6e9f249..b2466d9 100644 --- a/doc/docs/tutorials/provider-explicit/provider_explicit.ml +++ b/doc/docs/tutorials/provider-explicit/provider_explicit.ml @@ -333,11 +333,20 @@ end @mdexp.code *) -let _map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = +let map_n_times (type a) (module A : Mappable0) (x : a A.t) ~(f : a -> a) ~n : a A.t = let rec loop n x = if Int.equal n 0 then x else loop (n - 1) (A.map x ~f) in loop n x ;; +(* @mdexp.end + @mdexp.code *) + +let%expect_test "map n times" = + let result = map_n_times (module List) [ 0; 1; 2 ] ~f:Int.succ ~n:10 in + print_dyn (result |> Dyn.list Dyn.int); + [%expect {| [ 10; 11; 12 ] |}] +;; + (* @mdexp In this section we show how to do this with the *provider* library, leveraging