What is a Constraint kind?
Why would someone use it (in practice)?
What is it good for?
Could you give a simple code example to illustrate the answers to the previous two questions?
Why is it used in this code for example?
What is a Constraint kind?
Why would someone use it (in practice)?
What is it good for?
Could you give a simple code example to illustrate the answers to the previous two questions?
Why is it used in this code for example?
Copyright © 2021 Jogjafile Inc.
Well, I'll mention two practical things it allows you to do:
Maybe it's best to illustrate this with an example. One of the classic Haskell warts is that you cannot make a
Functorinstance for types that impose a class constraint on their type parameter; for example, theSetclass in thecontainerslibrary, which requires anOrdconstraint on its elements. The reason is that in "vanilla" Haskell, you'd have to have the constraint on the class itself:...but then this class only works for types that require specifically an
Ordconstraint. Not a general solution!So what if we could take that class definition and abstract away the
Ordconstraint, allowing individual instances to say what constraint they require? Well,ConstraintKindsplusTypeFamiliesallow that:(Note that this isn't the only obstacle to making a
Functorinstance toSet; see this discussion. Also, credit to this answer for theNoConstrainttrick.)This sort of solution hasn't been generally adopted just yet, though, because
ConstraintKindsare still more or less a new feature.Another use of
ConstraintKindsis to parametrize a type by a class constraint or class. I'll reproduce this Haskell "Shape Example" code that I wrote:Here the parameter of the
Objecttype is a type class (kind* -> Constraint), so you can have types likeObject ShapewhereShapeis a class:What the
Objecttype does is a combination of two features:GADTs), which allows us to store values of heterogeneous types inside the sameObjecttype.ConstraintKinds, which allows us to, instead of hardcodingObjectto some specific set of class constraints, have the users of theObjecttype specify the constraint they want as a parameter to theObjecttype.And now with that we can not only make a heterogeneous list of
Shapeinstances:...but thanks to the
Typeableconstraint inObjectwe can downcast: if we correctly guess the type contained inside anObject, we can recover that original type: