I’ve seen a few use cases for rank-2 polymorphism (the most prominent example being the ST monad), but none for a higher rank than that. Does anyone know of such a use case?
I’ve seen a few use cases for rank-2 polymorphism (the most prominent example being
Share
I may be able to help, although such beast are inevitably a bit involved. Here’s a pattern I sometimes use in developing well-scoped syntax with binding and de Bruijn indexing, bottled.
Normally, I’d use type classes to hide the worst of the gore, but if you unpack the dictionaries, this is what you’ll find.
The point is that
mangleis a rank-2 operation which takes a notion of thingy equipped with suitable operations polymorphic in the variable sets over which they work: operations which map variables to thingies get turned into term-transformers. The whole thing shows how to usemangleto generate both renaming and substitution.Here’s a concrete instance of that pattern:
We implement the term traversal just once, but in a very general way, then we get substitution by deploying the mkRenSub pattern (which uses the general traversal in two different ways).
For another example, consider polymorphic operations between type operators
An
IMonad(indexed monad) is somem :: (* -> *) -> * -> *equipped with polymorphic operatorsso those operations are rank 2.
Now any operation which is parametrized by an arbitrary indexed monad is rank 3. So, for example, constructing the usual monadic composition,
relies on rank 3 quantification, once you unpack the definition of
IMonad.Moral of story: once you’re doing higher order programming over polymorphic/indexed notions, your dictionaries of useful kit become rank 2, and your generic programs become rank 3. This is, of course, an escalation that can happen again.