A gentle introduction to Haskell

Paul Hudak, Joseph H. Fasel · ACM SIGPLAN Notices · 1992

For pedagogical purposes, when we wish to indicate that an expression e 1 evaluates, or "reduces," to another expression or value e 2 , we will write:For example, note that: inc (inc 3) ⇒ 5Haskell's static type system defines the formal relationship between types and values ( §4.1.3).The static type system ensures that Haskell programs are type safe; that is, that the programmer has not mismatched types in some way.For example, we cannot generally add together two characters, so the expression 'a'+'b' is ill-typed.The main advantage of statically typed languages is well-known: All type errors are detected at compile-time.Not all errors are caught by the type system; an expression such as 1/0 is typable but its evaluation will result in an error at execution time.Still, the type system finds many program errors at compile time, aids the user in reasoning about programs, and also permits a compiler to generate more efficient code (for example, no run-time type tags or tests are required).Here are two other useful polymorphic functions on lists that will be used later.Function head returns the first element of a list, function tail returns all but the first.head :: [a] -> a head (x:xs) = x tail :: [a] -> [a] tail (x:xs) = xsUnlike length, these functions are not defined for all possible values of their argument.A runtime error occurs when these functions are applied to an empty list.With polymorphic types, we find that some types are in a sense strictly more general than others in the sense that the set of values they define is larger.For example, the type [a] is more general than [Char].In other words, the latter type can be derived from the former by a suitable substitution for a.With regard to this generalization ordering, Haskell's type system possesses two important properties: First, every well-typed expression is guaranteed to have a unique principal type (explained below), and second, the principal type can be inferred automatically ( §4.1.3).In comparison to a monomorphically typed language such as C, the reader will find that polymorphism improves expressiveness, and type inference lessens the burden of types on the programmer.An expression's or function's principal type is the least general type that, intuitively, "contains all instances of the expression".For example, the principal type of head is [a]->a; [b]->a, a->a, or even a are correct types, but too general, whereas something like [Integer]->Integer is too specific.The existence of unique principal types is the hallmark feature of the Hindley-Milner type system, which forms the basis of the type systems of Haskell, ML, Miranda, 4 and several other (mostly functional) languages.[1..10] ⇒ [1,2,3,4,5,6,7,8,9,10] [1,3..10] ⇒ [1,3,5,7,9] [1,3..] ⇒ [1,3,5,7,9, ... (infinite sequence)More will be said about arithmetic sequences in Section 8.2, and "infinite lists" in Section 3.4.

Read the paper · More papers on PaperTik