A type expression is Haskell notation that states the type associated with a name or value-producing expression. A top-level type signature uses `::`, as in `name :: type`, and is commonly placed beside the corresponding definition. Haskell can infer many types, but explicit signatures document intended values and constrain how expressions are used. section 2.2 section 2.6
name :: type
A basic signature maps an identifier to its type; the definition may follow it. section 2.2
Atomic type names are themselves type expressions. Common choices include `Bool`, `Char`, `Int`, `Integer`, `Float`, and `Double`. A signature can resolve otherwise ambiguous numeric expressions: declaring `nano :: Double` requires its value to be a `Double`, while `mega :: Int` keeps its calculation in `Int`. section 2.2.1
Type expressions describe structured values as well as atomic ones:
- A list type brackets its element type: `[Int]` is a list whose elements must be `Int`; `[Double]` similarly directs inference for every element, including expressions inside the list. section 2.2.2
- A tuple type lists component types in parentheses: `(Int, Float)` describes a pair, while `(Int, Char, Double)` describes a three-part tuple. section 2.2.2
- A function type uses `->`: `(t -> a) -> [t] -> [a]` describes a function that accepts a converter and a list, then returns a list of converted values. section 2.5.2
intList :: [Int] intList = [1, 2, 3] boolList :: [Bool] boolList = [True] floatList :: [Float] floatList = [] doubleList :: [Double] doubleList = [1, 1 + 1, 1 + 2]
These signatures show list element types, including an empty list with a declared `Float` element type. section 2.2.2
Type variables such as `t` and `a` make a signature parametric: each occurrence of the same variable must be replaced consistently, but different variables may stand for different types. For `transform :: (t -> a) -> [t] -> [a]`, using an `Int -> String` converter makes the input `[Int]` and the result `[String]`. section 2.5.2
A signature can reveal a missing requirement
A proposed lookup signature, `member :: a -> [(a, b)] -> Bool`, describes keys and searched values with the same type. But using `(==)` requires comparable keys, so compilation reports a missing `Eq a` instance. The type expression must account for the operations used by the implementation. section 5.1.2
ghci> :type transform transform :: (t -> a) -> [t] -> [a]
GHCi can inspect a polymorphic function’s inferred type before concrete types are substituted. section 2.5.2

