Learning Haskell Programming
Master pure functional programming with Haskell's powerful type system. Build elegant, type-safe applications with fearless abstractions.
Why Learn Haskell?
- Pure Functional: Haskell's purely functional paradigm makes code predictable and easier to reason about
- Strong Static Typing: Catch errors at compile time with one of the most advanced type systems
- Lazy Evaluation: Compute values only when needed, enabling infinite data structures and composable abstractions
- Mathematical Elegance: Express complex ideas concisely with algebraic data types and type classes
- Real-World Impact: Used by Facebook, GitHub, Hasura, and financial institutions for reliable systems
Your Learning Path
Master Haskell's unique concepts step-by-step:
2-3 hours
2-3 hours
2-3 hours
3-4 hours
3-4 hours
4-5 hours
2-3 hours
Interactive Lessons
Click each lesson to expand and learn.
Basic Values and Types
Haskell is purely functional with strong static typing. Values are immutable and types are inferred automatically.
-- Basic types and values
x :: Int
x = 5
pi :: Double
pi = 3.14159
name :: String
name = "Alice"
isAdult :: Bool
isAdult = True
-- Type inference (no annotation needed)
y = 10 -- Haskell infers: Num a => a
-- Multiple bindings
area radius = pi * radius ^ 2
volume r h = pi * r ^ 2 * h
Functions and Pattern Matching
Functions in Haskell are first-class values. Pattern matching allows elegant case analysis.
-- Simple function
addOne :: Int -> Int
addOne x = x + 1
-- Multiple parameters
add :: Int -> Int -> Int
add x y = x + y
-- Pattern matching on tuples
fst :: (a, b) -> a
fst (x, _) = x
-- Pattern matching with guards
absoluteValue :: Int -> Int
absoluteValue n
| n >= 0 = n
| otherwise = -n
-- Recursive function
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n - 1)
Lists and Recursion
Lists are fundamental in Haskell. Pattern matching on lists enables elegant recursive functions.
-- List syntax
numbers :: [Int]
numbers = [1, 2, 3, 4, 5]
-- Cons operator (:)
list = 1 : 2 : 3 : []
-- List patterns
head :: [a] -> a
head (x:_) = x
tail :: [a] -> [a]
tail (_:xs) = xs
-- Recursive list processing
length :: [a] -> Int
length [] = 0
length (_:xs) = 1 + length xs
sum :: [Int] -> Int
sum [] = 0
sum (x:xs) = x + sum xs
-- List comprehension
squares = [x^2 | x <- [1..10]]
Algebraic Data Types
Algebraic data types allow you to define custom types with multiple constructors. Pattern matching makes them safe and expressive.
-- Simple sum type
data Bool = False | True
-- Type with parameters
data Maybe a = Nothing | Just a
-- Product types (records)
data Person = Person { name :: String
, age :: Int
, email :: String }
-- Recursive types
data Tree a = Leaf | Node a (Tree a) (Tree a)
-- Pattern matching
describeAge :: Person -> String
describeAge (Person _ age _)
| age < 13 = "child"
| age < 20 = "teenager"
| otherwise = "adult"
Maybe and Either Types
Haskell uses Maybe for nullable values and Either for error handling instead of exceptions.
-- Maybe for nullable values
data Maybe a = Nothing | Just a
-- Safe division
safeDivide :: Double -> Double -> Maybe Double
safeDivide _ 0 = Nothing
safeDivide x y = Just (x / y)
-- Either for error handling
data Either a b = Left a | Right b
parseAge :: String -> Either String Int
parseAge str = case reads str of
[(age, "")] -> if age >= 0
then Right age
else Left "Age cannot be negative"
_ -> Left "Invalid age format"
-- Using Maybe
lookup :: Eq a => a -> [(a, b)] -> Maybe b
lookup _ [] = Nothing
lookup key ((k,v):rest)
| key == k = Just v
| otherwise = lookup key rest
Type Classes
Type classes define shared behavior across types. They are similar to interfaces but more powerful.
-- Eq type class for equality
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
-- Ord type class for ordering
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
-- Show type class for string representation
class Show a where
show :: a -> String
-- Custom instance
data Color = Red | Green | Blue
instance Show Color where
show Red = "Red"
show Green = "Green"
show Blue = "Blue"
instance Eq Color where
Red == Red = True
Green == Green = True
Blue == Blue = True
_ == _ = False
Functors and Monads
Functors and Monads are powerful abstractions for working with values in contexts. They enable composable, expressive code.
-- Functor: things you can map over
class Functor f where
fmap :: (a -> b) -> f a -> f b
instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)
-- Applicative: apply functions in contexts
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
-- Monad: sequencing computations
class Applicative m => Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
-- Using Maybe monad
divideM :: Double -> Double -> Maybe Double
divideM _ 0 = Nothing
divideM x y = Just (x / y)
calc :: Maybe Double
calc = do
x <- divideM 10 2
y <- divideM x 5
return (y + 1)
Curated GitHub Repositories
Hand-picked repositories to accelerate your Rust learning.
Practice Projects
-
1. Command-Line Todo App
Build a CLI app using clap for argument parsing and serde for JSON serialization.
Key Concepts: ownership, structs, Result, file I/O, crates -
2. Multi-threaded Web Scraper
Scrape websites concurrently using reqwest and tokio for async networking.
Key Concepts: async/await, concurrency, error handling, HTTP requests -
3. Memory-Safe Linked List
Implement a doubly-linked list using Rc and RefCell to understand smart pointers.
Key Concepts: ownership, borrowing, smart pointers, unsafe code -
4. REST API with Actix-Web
Build a production-ready REST API with authentication, database, and error handling.
Key Concepts: web frameworks, async I/O, middleware, diesel ORM -
5. WebAssembly Game with Bevy
Create a 2D game using Bevy ECS framework and compile to WebAssembly.
Key Concepts: ECS architecture, WASM, game loops, resource management
Resources Hub
Official Docs
Tools
Practice
Community
Your Progress
Check off lessons as you complete them. Your progress is saved locally in your browser.