# OCaml 5.5 Polymorphic functions as function arguments

**URL:** <https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400>\
**Category:** Learning\
**Tags:** types\
**Created:** [July 28, 2026, 1:05pm UTC](https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400 "2026-07-28T13:05:03Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [July 28, 2026, 1:05pm UTC](https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400/1 "2026-07-28T13:05:03Z")

</div>

I have been trying to remove a use of a single field polymorphic record using OCaml 5.5 polymorphic functions as function arguments.

While I can see the feature being useful in some restricted cases. I didn’t succeed to get rid of my use. For example in:

```ocaml
type observer = { observe : 'a. (unit -> 'a) -> 'a }
let blind = { observe = (fun f -> f ()) }

module Observe : sig
  val run : ?observer:observer -> (unit -> 'a) -> 'a
end = struct
  let run ?(observer = blind) f = observer.observe f
end

```

I would have liked to simply remove the field:

```auto
type observer = 'a. unit -> 'a -> 'a 

```

But that’s not possible I have to reveal the `'a` and quantify all over the place when I use `observer` arguments. First that’s rather noisy, second it doesn’t seem to work with optional arguments. This code fails with:

```auto
type 'a observer = (unit -> 'a) -> 'a
let blind f = f ()

module Observe : sig
  val run : ?observer:('a. 'a observer) -> (unit -> 'a) -> 'a
end = struct
  let run ?(observer = blind) f = observer f
end

```

```sh
File "poly/poly.ml", line 4, characters 22-39:
4 | val run : ?observer:('a. 'a observer) -> (unit -> 'a) -> 'a
                          ^^^^^^^^^^^^^^^^^
Error: Optional parameter observer cannot be polymorphic

```

Did I miss something or is that a limitation we are going to have for the foreseeable future?

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [July 28, 2026, 1:44pm UTC](https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400/2 "2026-07-28T13:44:25Z")

</div>

> [@dbuenzli](#):
>
> Did I miss something or is that a limitation we are going to have for the foreseeable future?

My understanding is that this is a hard limitation (but typing experts will confirm). Basically, optional arguments are sugar for arguments of type `'a option`, so you are asking to instantiate `'a` at a polymorphic type, something like `('b. unit -> 'b -> 'b) option` which is not really supported in any general way in OCaml’s type system.

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [July 28, 2026, 2:57pm UTC](https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400/3 "2026-07-28T14:57:46Z")

</div>

Polymorphic types with an explicit universal quantification are still second-class citizen in the type system after the polymorphic parameters change.

My summary would be that polymorphic parameters remove the need to define a record with a polymorphic field which is used once in one function. However, as soon as the code is using values with such type as a first-class citizens, it is still required to define a record definition. This is at least partially for theoretical reasons: the record boxing and unboxing make it explicit which view of the type one should adopt. As an illustration of this double vision issue, in

```ocaml
type id = { f: 'a. 'a -> 'a }
let id x = x
let f a = a {f=id} 0 "0"
let g a = a id 0 "0"

```

the function `f` and `g` have distinct requirement over the function `a`.

From this point of view, polymorphic parameters is identifying that for a function, there is a relatively intuitive choice on when to box (during function call) and unbox (in the function body) the parameters of the function.

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [July 28, 2026, 3:26pm UTC](https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400/4 "2026-07-28T15:26:45Z")

</div>

Before I forget to mention it, there are valid usability points: it might be nice to be able to define abbreviation for polymorphic type or to have a form of polymorphic optional parameters.  
These changes would possibly help to reduce the number of polymorphic records in library API.

But my impression is also that both features have potentially sharp usability edges that would require some careful design to circumvent.

---

<div class="post-metadata">

**Author:** ![Alistair](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/alistair/32/3477_2.png) [@Alistair](https://discuss.ocaml.org/u/Alistair)\
**Post date:** [August 5, 2026, 2:17pm UTC](https://discuss.ocaml.org/t/ocaml-5-5-polymorphic-functions-as-function-arguments/18400/5 "2026-08-05T14:17:51Z")

</div>

I’ve opened a [PR](https://github.com/ocaml/ocaml/pull/14985) addressing the lack of support for optional polymorphic parameters.

While it doesn’t fix the other pain point that @dbuenzli highlights (the lack of abbreviations for polymorphic types), it would allow one to implement:

```ocaml
type 'a observer = (unit -> 'a) -> 'a
let blind f = f ()

module Observe : sig
  val run : ?observer:('a. 'a observer) -> (unit -> 'a) -> 'a
end = struct
  let run ?(observer : 'a. 'a observer = blind) f = observer f
end

```

> My understanding is that this is a hard limitation (but typing experts will confirm)

The reason this is possible is that, while supporting an arbitrary higher-rank type like `('a. 'a observer) option` is a lot of work, optional arguments are second-class (much like labelled arguments, which can already have polymorphic types).

We can exploit this restriction along with using the encoding for `'a. ('a observer) option` for the parameter type. This type is less general than `('a. 'a observer) option`, but it should be sufficient for most use cases and fits naturally into the existing treatment for polymorphic parameters.
