Guarded Methods in OCaml: Encoding Type Constraints on Individual Methods

Guarded methods let you attach constraints to the receiver for specific methods only, but OCaml doesn't support them syntactically. This note shows how to encode them using type equality witnesses (GADTs). It starts with the problem of defining a `flatten` method on a list class, compares three approaches—moving the method outside, extension methods, and guarded methods—and then provides a concrete OCaml implementation using the `eq` type to enforce constraints like `'a = 'b list` or `'a = int`. The technique enables fine-grained method-level polymorphism without escaping the class.
The goal is to allow adding a constraint to certain methods so that they are only accessible if the receiver's type satisfies it.
- spankalee
Cool to see this pop up today.
I'm building a new language and just a couple of days ago the concept of guard methods came up as I was trying to tighten up equality semantics to be more like Swift.
Things like Array.contains() only work if the element type implements the Equatable interface, so it would be a guard method. Maybe something like:
class Array<T> {
contains(value: T): boolean where T extends Equatable { ... }
}
Or possibly a constraint on the `this` type, TypeScript style:
class Array<T> {
contains(this: Array<T extends Equatable>, value: T): boolean { ... }
}
https://github.com/elematic/zena/blob/8d77f2b36001078f4d5054...
- msdz
Nice article, but I don’t fully understand why the author argues for such an aversion to static functions.
> Moreover, it breaks the systematic approach of sending messages to an instance (often presented as one of the key arguments in favor of object-oriented programming).
Is this just a matter of “the code will become spaghetti once too many classes/methods/implementations exist”? And, conversely, is a non-static method with a constrained, i.e. somehow different type (or also the approach of moving a method outside of the class proper) not more confusing?
- wavemode
> Although guarded methods seem necessary, unfortunately, I don’t know of any mainstream languages that allow their definition.
C++ has this feature. When you define a template class, you can use SFINAE (or, in modern C++, concepts) to make it so that certain methods only exist if the template parameter meets certain requirements.
(Though even this is often unnecessary - for something like your `flatten` example, you could just go ahead and define it unrestricted. Methods of template classes are typechecked lazily - in other words, they don't need to successfully typecheck unless they're called. For this specific use case, SFINAE/concepts would just make the error message nicer.)
Rust also has this feature, with conditional impls.