Est. 1990 Intermediate

Haskell

The purely functional programming language that pioneered lazy evaluation, type classes, and monads - influencing modern language design across the industry.

Created by Haskell Committee (Simon Peyton Jones, Philip Wadler, et al.)

Paradigm Purely Functional, Lazy Evaluation, Strongly Typed
Typing Static, Strong, Inferred
First Appeared 1990
Latest Version Haskell 2010 (GHC 9.10, 2024)

Haskell is a purely functional programming language that has profoundly influenced modern software development. Even if you never write Haskell professionally, understanding its concepts will make you a better programmer in any language.

History & Origins

In the late 1980s, the functional programming community was fragmented. Multiple research groups had created similar lazy functional languages - Miranda, LML, Orwell, and others - but there was no common language for collaboration and teaching.

The Birth of Haskell

At the 1987 Conference on Functional Programming Languages and Computer Architecture (FPCA), researchers decided to form a committee to design a new, open standard for lazy functional languages. The goals were ambitious:

  1. Suitable for teaching, research, and applications
  2. Completely described via formal semantics
  3. Freely available - no proprietary restrictions
  4. Based on established ideas - not experimental

The committee, which included Simon Peyton Jones, Philip Wadler, and other luminaries, worked for three years to produce Haskell 1.0 in 1990.

The Name

Haskell is named after Haskell Brooks Curry (1900-1982), an American mathematician and logician. Curry’s work on combinatory logic is fundamental to functional programming. The concept of “currying” - transforming functions with multiple arguments into sequences of functions with single arguments - is named after him (though Moses Schönfinkel invented it first).

What Makes Haskell Different

1. Pure Functions

In Haskell, functions are mathematically pure - they always return the same output for the same input and have no side effects:

1
2
3
4
5
6
-- This function will ALWAYS return 6 for input 3
double :: Int -> Int
double x = x * 2

-- Pure functions can be reasoned about mathematically
-- double 3 = 3 * 2 = 6, always

This purity enables powerful compiler optimizations and makes code easier to test and reason about.

2. Lazy Evaluation

Haskell evaluates expressions only when their values are actually needed:

1
2
3
4
5
6
7
-- This creates an infinite list!
naturals = [1..]

-- But we can safely take just what we need
firstTen = take 10 naturals  -- [1,2,3,4,5,6,7,8,9,10]

-- The rest is never computed

Lazy evaluation enables working with infinite data structures, building computations modularly, and avoiding unnecessary work.

3. Strong Static Type System

Haskell’s type system catches errors at compile time while requiring minimal type annotations thanks to type inference:

1
2
3
4
5
6
-- The compiler infers: length :: [a] -> Int
length []     = 0
length (_:xs) = 1 + length xs

-- Type errors are caught before the program runs
-- length "hello" + "world"  -- Won't compile!

4. Type Classes

Haskell introduced type classes, a way to define generic interfaces:

1
2
3
4
5
6
7
8
9
-- The Eq class defines equality
class Eq a where
    (==) :: a -> a -> Bool

-- Any type can implement Eq
instance Eq Bool where
    True  == True  = True
    False == False = True
    _     == _     = False

Type classes inspired traits in Rust, protocols in Swift, and type classes in Scala.

5. Algebraic Data Types

Complex data structures are built by combining simpler types:

1
2
3
4
5
6
7
8
-- Sum type: a value is one of several variants
data Color = Red | Green | Blue

-- Product type: a value contains multiple fields
data Point = Point Int Int

-- Combination: a tree is either empty or a node with children
data Tree a = Empty | Node a (Tree a) (Tree a)

6. Pattern Matching

Elegant destructuring of data types:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- Define behavior for each case
describe :: Color -> String
describe Red   = "Roses are red"
describe Green = "Grass is green"
describe Blue  = "Sky is blue"

-- Recursive patterns
sumTree :: Tree Int -> Int
sumTree Empty        = 0
sumTree (Node x l r) = x + sumTree l + sumTree r

The Monad Breakthrough

One of Haskell’s most famous (and initially confusing) contributions is the monad, which elegantly handles side effects in a pure language.

The Problem

If functions can’t have side effects, how do you:

  • Read user input?
  • Write to files?
  • Generate random numbers?
  • Handle errors?

The Solution

Monads encapsulate computational contexts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
-- The IO monad represents computations that interact with the world
main :: IO ()
main = do
    putStrLn "What's your name?"
    name <- getLine
    putStrLn ("Hello, " ++ name ++ "!")

-- The Maybe monad handles optional values
safeDivide :: Int -> Int -> Maybe Int
safeDivide _ 0 = Nothing
safeDivide x y = Just (x `div` y)

-- Chain operations that might fail
calculate :: Int -> Int -> Int -> Maybe Int
calculate x y z = do
    a <- safeDivide x y
    b <- safeDivide a z
    return (a + b)

The monad pattern has spread far beyond Haskell - JavaScript Promises, Rust’s Option and Result, Swift’s optionals, and reactive programming all use monadic concepts.

GHC: The Glasgow Haskell Compiler

While the Haskell standard defines the language, GHC (Glasgow Haskell Compiler) has become the de facto implementation. GHC features:

Language Extensions

GHC provides numerous extensions beyond the standard:

  • GADTs - Generalized algebraic data types
  • TypeFamilies - Type-level functions
  • TemplateHaskell - Compile-time metaprogramming
  • LinearTypes - Resource-tracking types

Optimization

GHC produces highly efficient code through:

  • Aggressive inlining
  • Deforestation (eliminating intermediate data structures)
  • Strictness analysis (evaluating eagerly when safe)
  • LLVM backend for native code generation

The Haskell Ecosystem

Build Tools

  • Cabal - The original package manager and build tool
  • Stack - Reproducible builds with curated package sets
  • GHCup - Installer for GHC and tools
  • Haskell Language Server - IDE support
  • lens - Composable getters/setters for complex data
  • parsec/megaparsec - Parser combinator libraries
  • aeson - JSON parsing and generation
  • conduit/pipes - Streaming data processing
  • servant - Type-safe REST API framework
  • QuickCheck - Property-based testing (invented in Haskell!)

Why Learn Haskell?

1. It Changes How You Think

Haskell’s constraints force you to think differently:

  • No mutable state makes you find cleaner solutions
  • Type-driven development catches bugs early
  • Function composition encourages modular design

These skills transfer to every other language.

2. Concepts Spreading Everywhere

Features pioneered or popularized by Haskell appear in:

  • Rust: Algebraic types, pattern matching, traits, Option/Result
  • Swift: Optionals, value types, protocol-oriented programming
  • TypeScript: Discriminated unions, type inference
  • Java/C#: Lambda expressions, streams, Optional
  • JavaScript: Promises, immutability trends, functional patterns

3. It’s Practical When You Need It

For domains requiring correctness:

  • Financial systems
  • Compilers and language tools
  • Cryptography
  • Concurrent systems

Haskell’s guarantees provide real value.

Getting Started

Haskell source files use the .hs extension. The basic structure is:

1
2
3
4
5
6
7
8
9
-- Module declaration
module Main where

-- Import statements
import Data.List (sort)

-- Function definitions
main :: IO ()
main = print "Hello, World!"

REPL: GHCi

Haskell comes with an interactive environment:

$ ghci
GHCi, version 9.6.1: https://www.haskell.org/ghc/
Prelude> 2 + 2
4
Prelude> map (*2) [1,2,3]
[2,4,6]
Prelude> :type map
map :: (a -> b) -> [a] -> [b]

Your First Function

1
2
3
4
5
6
7
-- In hello.hs
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)

main :: IO ()
main = print (factorial 20)

Run with:

1
runghc hello.hs

A Complete Example

Here’s a more complete Haskell program showing various features:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
module Main where

import Data.List (sortBy)
import Data.Ord (comparing)

-- Define a data type
data Person = Person
    { name :: String
    , age  :: Int
    } deriving (Show, Eq)

-- Pure function to calculate average age
averageAge :: [Person] -> Double
averageAge []     = 0
averageAge people = fromIntegral total / fromIntegral count
  where
    total = sum (map age people)
    count = length people

-- Sort people by age
sortByAge :: [Person] -> [Person]
sortByAge = sortBy (comparing age)

-- Find adults
adults :: [Person] -> [Person]
adults = filter (\p -> age p >= 18)

main :: IO ()
main = do
    let people = [ Person "Alice" 30
                 , Person "Bob" 17
                 , Person "Charlie" 25
                 ]

    putStrLn "All people:"
    mapM_ print people

    putStrLn "\nAdults only:"
    mapM_ print (adults people)

    putStrLn $ "\nAverage age: " ++ show (averageAge people)

The Haskell Community

Resources

  • haskell.org - Official site with tutorials
  • Haskell Wiki - Community documentation
  • Hackage - Package repository
  • Hoogle - Search by type signature
  • School of Haskell - Interactive tutorials

Books

  • “Learn You a Haskell for Great Good!” - Beginner-friendly
  • “Real World Haskell” - Practical applications
  • “Haskell Programming from First Principles” - Comprehensive

Community

  • Haskell Discourse forum
  • r/haskell subreddit
  • Functional Programming Slack/Discord
  • Haskell Weekly newsletter

Continue to the Hello World tutorial to write your first Haskell program.

Timeline

1987
FPCA conference: researchers agree to create an open standard for lazy functional languages
1990
Haskell 1.0 released, named after logician Haskell Curry
1996
Haskell 1.3 introduces monadic I/O, solving the 'awkward squad' of imperative features
1998
Haskell 98 published - the first stable, standardized version
2003
GHC becomes the de facto standard compiler with advanced optimizations
2010
Haskell 2010 standard released with minor revisions
2024
GHC 9.10 released with continued performance improvements and language extensions

Notable Uses & Legacy

Facebook (Meta) Spam Detection

Sigma system processes millions of requests per second using Haskell for spam and abuse detection.

GitHub Semantic Code Analysis

GitHub's semantic library for parsing and analyzing code across multiple languages is written in Haskell.

Standard Chartered Bank

Uses Haskell extensively for financial modeling and risk analysis in trading systems.

Cardano Blockchain

The Cardano cryptocurrency platform is written primarily in Haskell for its mathematical correctness guarantees.

Pandoc Document Converter

The universal document converter supporting dozens of formats is written in Haskell.

XMonad Window Manager

A popular tiling window manager for X11, configured and extended in Haskell itself.

Language Influence

Influenced By

Miranda ML Lisp ISWIM APL FP

Influenced

Rust Swift Scala F# Elm PureScript Idris Agda

Running Today

Run examples using the official Docker image:

docker pull haskell:9.6

Example usage:

docker run --rm -v $(pwd):/app -w /app haskell:9.6 runghc hello.hs

Topics Covered

Last updated: