Functions may have polymorphic arguments, subject to three restrictions:
- Such functions must have explicit type signatures, using forall to bind polymorphic type variables, e.g.
g :: (forall a. a -> a) -> (Bool, Char)
- In the definition of the function, polymorphic arguments
- must be matched on the left-hand side, and
- can only be matched by a variable or wildcard (_) pattern. The variable then has the polymorphic type of the corresponding argument, e.g.
g f = (f True, f 'a')
- When such a function is used, it must be applied to at least as many arguments to include the polymorphic ones (so it's a good idea to put those first). Each expression must have a generalized type at least as general as that declared for the corresponding argument, e.g.
g id g undefined
The more general RankNTypes relax restrictions 2(1) and 3.
- PolymorphicComponents do the same thing for data constructors.
- add RankNTypes or Rank2Types
- simple type inference
- offered by GHC and Hugs for years
- enables runST and similar devices
- used in cheap deforestation
- useful with non-regular (or nested) types
- useful with PolymorphicComponents
- functions with rank-2 types are not first class
- can be awkward in comparison with RankNTypes