A definition is predicative if it is not circular. An impredicative definition, in contrast, indirectly refers to the object being defined by quantifying over the domain that includes the object. Here is an example of a predicative Haskell definition of the type P , and of a sample term prd of that type:

type P = forall a. a -> [a] prd :: P prd x = [x]

P

a

P

prd

tprd1 = case prd prd of [f] -> f True

prd

tprd2 = case prd prd of [f] -> (f True, f 'a') Error: Couldn't match expected type `Bool' with actual type `Char'

Haskell also permits impredicative definitions, like the following:

newtype I = I{unI :: forall a. a -> [a]} imprd :: I imprd = I (\x -> [x]) tim = case unI imprd imprd of [I f] -> (f True, f 'a')

I

a

I

I

tim

Injectivity of type constructors means that a type constructor T (defined by a data declaration) gives distinct types when applied to distinct arguments. Contrapositively:

T a ~ T b implies a ~ b

~

Haskell has type functions that do the case analysis on types, extracting their components. Such type functions can be implemented via functional dependencies, GADTs, type or data families. The type family below

type family Elem x :: * type instance Elem [a] = a type instance Elem (Maybe a) = a