Chapter 7. Interfaces: using constrained generic types
This chapter covers
- Constraining generic types using interfaces
- Implementing interfaces for specific contexts
- Using interfaces defined in the Prelude
In chapter 2, you saw that generic function types with type variables could be constrained so that the variables stood for a more limited set of types. For example, you saw the following function for doubling a number in any numeric type:
double : Num a => a -> a double x = x + x
The type of double includes a constraint, Num a, which states that a can only stand for numeric types. Therefore, you can use double with Int, Nat, Integer, or any other numeric type, but if you try to use it with a non-numeric type, such as Bool, Idris will report an error.
You’ve seen a few such constraints, such as Eq for types that support equality tests and Ord for types that support comparisons. You’ve also seen functions that rely on other constraints that we haven’t discussed in detail, such as map and >>=, which rely on Functor and Monad, respectively. We haven’t yet discussed how these constraints are defined or introduced.
In this chapter, we’ll discuss how to define and use constrained generic types using interfaces. In the type declaration for double, for example, the constraint Num a is implemented by an interface, Num, which describes arithmetic operations that will be implemented in different ways for different numeric types.