Explain the Pi type (x : A) -> B(x) and how it generalizes both ordinary function types and universal quantification.
Think about your answer, then reveal below.
Model answer: The Pi type (x : A) -> B(x) is a function type where the return type B(x) can depend on the input value x. When B does not actually depend on x, it reduces to the ordinary function type A -> B. Under Curry-Howard, it corresponds to universal quantification: 'for all x : A, B(x).' A value of this type is a function that, given any x of type A, produces a value of type B(x) — simultaneously a program (a function) and a proof (of the universal statement).
This generalization is what makes dependent type theory so powerful. Ordinary polymorphism (forall a. a -> a) is a special case where the type parameter is a type, not a value. Dependent types allow the parameter to be any value: a natural number, a list, a proof. The function head : (n : Nat) -> Vec(A, n+1) -> A takes a natural number n (which it may not even use computationally) and a non-empty vector, returning an element. The type-level computation n+1 guarantees the vector is non-empty, making a runtime bounds check unnecessary.