There are always tradeoffs. Every new feature in any language comes with additional ways of going wrong. But given that OCaml is quite explicit, the scope for going wrong doesn’t seem too much to me.
How do we do this today? We write down a type definition and use some ppx plugin.
type t = A of int | B of int [@@deriving show]
Now we have some additional functions autogenerated in our module called pp
, show
etc. The functions are generated within the module that type t
is in. It does not pollute the global environment.
Lets take a more complicated example. This time using the refl
library to generate a runtime type representation that you can use to generate a debug printer among other things.
(Example reproduced from https://github.com/thierry-martinez/refl/blob/master/README.md – see that document for more details)
type 'a binary_tree =
| Leaf
| Node of { left : 'a binary_tree; label : 'a; right : 'a binary_tree }
[@@deriving refl]
Now we can obtain the runtime type representation for string binary_tree
by using the ppx form [%refl: ... ]
# Refl.show [%refl: string binary_tree] []
(Node { left = Leaf; label = "root"; right = Leaf });;
- : string = "Node { left = Leaf; label = \"root\"; right = Leaf }"
(Note that we need to explictly specify what type appears for 'a
. Here it is string
).
Now to show
something, we need to also explictly pass the runtime type representation to the Refl.show function (here that representation can be obtained by using the ppx form [%refl: string binary_tree]
) .
Note that there was no inference of any kind about obtaining the runtime type representation from the ambient environment anywhere
The discussion of this thread has been mainly about moving some of the tedium and
custom nature of using ppxes, various opam libraries etc. to incorporate this functionality into the standard Ocaml distribution. This is so that newbies (and others) could just be able do this without having to learn ppxes, choose from a menagerie of libraries, have to change the dune config to use the ppx etc. in order to simply debug print something.
This would continue to be explicit in the future too, if what we have been discussing on this thread is ever realized.
Here refl
built a runtime representation for me because I used their ppx. I could have used the combinators provided by refl and built a runtime representation myself too if I didn’t use refl’s ppx. (Of course, this manually build representation using refl’s combinators would need to be consistent with the structure of the type to be useful within refl).
In the future, you could have a representation auto generated by the Ocaml stdlib (the equivalent situation in which refl’s ppx did that for me above). This auto generated representation should be OK for most users. But then you could have other alternate representations build by different tools and ppxes perhaps with some additional metadata. Everytime you would call a method that required a runtime representation you would need to pass it explictly with the value and it would not be inferred for you.
So in that respect it is different from typeclasses in Rust/Haskell.
Also, I don’t think anybody is claiming that there would be a unified single representation – you could have multiple representations for different use cases.
Everything remains explicit. The scope for messing up is not very much now with ppxes and neither will that scope be increased if this functionality were to be provided in the OCaml standard distribution in the future in some way.