# Ad hoc polymorphism and usability

**URL:** <https://discuss.ocaml.org/t/ad-hoc-polymorphism-and-usability/9059>\
**Category:** Ecosystem\
**Created:** [December 28, 2021, 1:40pm UTC](https://discuss.ocaml.org/t/ad-hoc-polymorphism-and-usability/9059 "2021-12-28T13:40:57Z")\
**Posts on this page:** 1\
**Showing post:** 17

<div class="post-metadata">

**Author:** ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)\
**Post date:** [December 30, 2021, 4:31pm UTC](https://discuss.ocaml.org/t/ad-hoc-polymorphism-and-usability/9059/17 "2021-12-30T16:31:58Z")

</div>

> [@yawaramin](#):
>
> The way Go does this is pretty similar to the way OCaml does it right now with functors or first-class modules.

It’s even simpler than that, a golang interface is just a simple dictionary of closures. It’s similar to the [solution given by @jobjo to the shape design problem](https://discuss.ocaml.org/t/the-shape-design-problem/7810/31). What I did in this thread, or what do RWO, with first-class modules is to make explicit the structure of these closures.

Look at the Golang example for their interface system ([interface in golang](https://go.dev/tour/methods/9)). When you want to implement an interface for a given type, you just have to define a closure that captures a value of that type:

```golang
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}

```

in this case `Abs` is a closure that encapsulates a `MyFloat` named `f`. And the system will automatically instantiates the right dictionary when you convert a `MyFloat` to an `Abser` (this is the implicit part of modular implicits, that you also find with Haskell’s type classes or Rust’s traits).

They define their interface this way:

```golang
type Abser interface {
	Abs() float64
}

```

In OCaml, we will use this dictionary of closures:

```ocaml
type abser = { abs : unit -> float }

```

but, since this type will be populated with closures, its values will be be partial applications of closed functions of this following type (I just remove the `unit` to simplify):

```ocaml
type 'a abser_closed : { abs : 'a -> float }

```

And now, to complete the closure, we need a partial application and hence a value to apply the closed function. So the original `abser` type is near to this one:

```ocaml
type 'a abser_closure = 'a abser_closed * 'a

```

And since the type of the value encapsulated in the closure is unknown to the user, we need to wrap this in an existential:

```ocaml
type abser = Abser : 'a abser_closure

```

We could also have use first-class modules, since the parametric dictionary `'a abser_closed` is equivalent to this one:

```ocaml
module type Abser = sig
  type t
  val abs : t -> float
end

type 'a abser_closed_with_module = (module Abser with type t = 'a)

```

The interest of first-class module is that we can divide the code in clear and separate compilation units, and then create easily a closures dictionary from them as illustrated in the chapter about first-class module in RWO.

By the way, that’s also how works ad hoc polymorphism in OOP : an object is just a dictionary of closures that shared the same environment (the instance variables).

Nevertheless, with simple closures, you will end up with problem as soon as you do not only consume your value but you also produce them, like in this interface:

```ocaml
module type Abser_extended = sig
  include Abser
  val double : t -> t
end

```

Here, you can still use the solution with first-class module and existential GADT. But, as soon as you want to add binary operator (for instance overloading the addition) you’re stuck with this solution and you need to rely on the highest solution for _ad hoc_ polymorphism in OCaml: functor or first-class functor (but without existential GADT).

Geometrically, the solution with GADT can be seen with this cone:

[![](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.ilemaths.net%2Fimg%2Fforum_img%2F0501%2Fforum_501149_1.jpg&f=1&nofb=1) ](https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.ilemaths.net%2Fimg%2Fforum_img%2F0501%2Fforum_501149_1.jpg&f=1&nofb=1)

the circular base of the cone represent all the types of the language that can implement the `abser` interface (each point is a type) and the top or apex A of the cone is precisely the type `abser`. You can see it as a directed graph where each edge (that goes from the base to the apex) is labelled with the dictionary (the first-class module) that shows how a type can be viewed as an `abser`. Now, when you want to use an `asber` value, you have to reverse the direction of the graph: the edges go from the apex to the circular base, and the purpose of such a value is to _dispatch_ the right dictionary to the right type. I guess that the _dispatching_ mechanism at the heart of some form of _ad hoc_ polymorphism can be well seen with the shape of the cone.

To conclude, there is something that we don’t see with the cone: in the two previous examples (`Abser` and `Abser_extended`) the apex also belongs to the base circle (an `abser` value also satisfies the `asber` interface), but it’s not the case when we have binary operators and that’s why we need the full power of functors (the implicit part is just here to reduce boilerplate).

---

_[View the full topic](https://discuss.ocaml.org/t/ad-hoc-polymorphism-and-usability/9059)._
