A brief introduction to Haskell
- A language developed by the programming languages research community.
- Is a lazy, purely functional language (that also has imperative features such as side effects and mutable state, along with strict evaluation)
- Born as an open source vehicle for programming language research
- One of the youngest children of ML and Lisp
- Particularly useful for programs that manipulate data structures (such as compilers and interpreters), and for concurrent/parallel programming
Inspired by the Introduction to OCaml.
- 1990. Haskell 1.0
- 1991. Haskell 1.1
- 1993. Haskell 1.2
- 1996. Haskell 1.3
- 1997. Haskell 1.4
- 1998. Haskell 98
- 2000-2006. Period of rapid language and community growth
- ~2007. Haskell Prime
2 Haskell features
Has some novel features relative to Java (and C++).
- Immutable variables by default (mutable state programmed via monads)
- Pure by default (side effects are programmed via monads)
- Lazy evaluation: results are only computed if they're required (strictness optional)
- Everything is an expression
- First-class functions: functions can be defined anywhere, passed as arguments, and returned as values.
- Both compiled and interpreted implementations available
- Full type inference -- type declarations optional
- Pattern matching on data structures -- data structures are first class!
- Parametric polymorphism
- Bounded parametric polymorphism
These are all conceptually more advanced ideas.
Compared to similar functional languages, Haskell differs in that it has support for:
- Lazy evaluation
- Pure functions by default
- Monadic side effects
- Type classes
- Syntax based on layout
The GHC Haskell compiler, in particular, provides some interesting extensions:
- Generalised algebraic data types
- Impredicative types system
- Software transactional memory
- Parallel, SMP runtime system
3 The Basics
3.1 Interacting with the language
Haskell is both compiled and interpreted. For exploration purposes, we'll consider interacting with Haskell via the GHCi interpreter:
- expressions are entered at the prompt
- newline signals end of input
Here is a GHCi sessoin, starting from a UNIX prompt.
$ ghci ___ ___ _ / _ \ /\ /\/ __(_) / /_\// /_/ / / | | GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| | http://www.haskell.org/ghc/ \____/\/ /_/\____/|_| Type :? for help.
Loading package base-1.0 ... linking ... done.Here the incredibly simple Haskell program
Prelude> let x = 3 + 4
We can ask the system what type it automaticaly inferred for ourvariable.
Prelude> :t x x :: Integer
A variable evaluates to its value.
Prelude> x 7
Prelude> x + 4 11
new binding for a variable with local scope.
Prelude> let x = 4 in x + 3 7
Alternatively, declarations typed in at the top level are like an open-ended let:
Prelude> let x = 4 Prelude> let y = x + 3 Prelude> x * x 16 Prelude> :t x x :: Integer Prelude> :t y y :: Integer Prelude> :t x * x x * x :: Integer
Notice that type inference infers the correct type for all the expressions, without us having to ever specify the type explicitly.
4 Basic types
There is a range of basic types, defined in the language Prelude.
Int -- bounded, word-sized integers Integer -- unbounded integers Double -- floating point values Char -- characters String -- strings () -- the unit type Bool -- booleans [a] -- lists (a,b) -- tuples / product types Either a b -- sum types Maybe a -- optional values
7 12312412412412321 3.1415 'x' "haskell" () True, False [1,2,3,4,5] ('x', 42) Left True, Right "string" Nothing, Just True
These types have all the usual operations on them, in the standard libraries.
- The Prelude contains the core operations on basic types. It is imported by default into every Haskell module. For example;
+ - div mod && || not < > == /=
To use functions from these modules you have to import them, or in GHCi, refer to the qualified name, for example to use the toUpper function on Chars:
Prelude> Char.toUpper 'x' 'X' Prelude> :m + Char Prelude Char> toUpper 'y' 'Y'
In a source file, you have to import the module explicitly: