module Main where
main :: IO ()
main = putStrLn "Hello, World!"
Functions and Pattern Matching
Example:
module Factorial where
-- Recursive factorial with pattern matching
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
-- Using guards
absoluteValue :: Int -> Int
absoluteValue x
| x < 0 = -x
| otherwise = x
-- Case expression
describeNumber :: Int -> String
describeNumber n = case n of
0 -> "zero"
1 -> "one"
_ -> "many"
Data Types and Type Classes
Example:
module Types where
-- Algebraic data types
data Maybe a = Just a | Nothing
deriving (Show, Eq)
data Either a b = Left a | Right b
deriving (Show, Eq)
-- Record syntax
data Person = Person
{ name :: String
, age :: Int
, email :: String
} deriving (Show, Eq)
-- Type synonym
type Name = String
type Age = Int
-- Newtype wrapper
newtype Email = Email String
deriving (Show, Eq)
-- Type class definition
class Describable a where
describe :: a -> String
-- Type class instance
instance Describable Person where
describe p = name p ++ " is " ++ show (age p) ++ " years old"
Higher-Order Functions and Lambdas
Example:
module HigherOrder where
-- Map, filter, and fold
doubleList :: [Int] -> [Int]
doubleList xs = map (*2) xs
evenNumbers :: [Int] -> [Int]
evenNumbers xs = filter even xs
sumList :: [Int] -> Int
sumList xs = foldl (+) 0 xs
-- Lambda functions
addOne :: [Int] -> [Int]
addOne = map (\x -> x + 1)
-- Function composition
processData :: [Int] -> Int
processData = sum . filter even . map (*2)
-- Partial application
add :: Int -> Int -> Int
add x y = x + y
addFive :: Int -> Int
addFive = add 5
-- Using backticks for infix
divBy :: Int -> Int -> Int
divBy x y = x `div` y
List Comprehensions
Example:
module Lists where
-- Basic list comprehension
squares :: [Int]
squares = [x^2 | x <- [1..10]]
-- With filters
evenSquares :: [Int]
evenSquares = [x^2 | x <- [1..10], even x]
-- Multiple generators
pairs :: [(Int, Int)]
pairs = [(x, y) | x <- [1..3], y <- [1..3], x /= y]
-- Pythagorean triples
pythagorean :: Int -> [(Int, Int, Int)]
pythagorean n = [(a, b, c) | a <- [1..n],
b <- [a..n],
c <- [b..n],
a^2 + b^2 == c^2]
-- String processing
uppercase :: String -> String
uppercase str = [toUpper c | c <- str]
where
toUpper c = if c >= 'a' && c <= 'z'
then toEnum (fromEnum c - 32)
else c
Monads and Do Notation
Example:
module Monads where
import Control.Monad (when, unless)
-- Maybe monad
safeDivide :: Double -> Double -> Maybe Double
safeDivide _ 0 = Nothing
safeDivide x y = Just (x / y)
calculateRatio :: Double -> Double -> Maybe Double
calculateRatio a b = do
x <- safeDivide a b
y <- safeDivide x 2
return (y + 1)
-- IO monad
greetUser :: IO ()
greetUser = do
putStrLn "What's your name?"
name <- getLine
putStrLn ("Hello, " ++ name ++ "!")
-- List monad
pairs :: [Int] -> [Int] -> [(Int, Int)]
pairs xs ys = do
x <- xs
y <- ys
return (x, y)
-- Guard in do notation
positiveProducts :: [Int] -> [Int] -> [Int]
positiveProducts xs ys = do
x <- xs
y <- ys
let product = x * y
if product > 0
then return product
else []
Functors, Applicatives, and Monads
Example:
module Abstractions where
-- Functor instance for custom type
data Box a = Box a deriving (Show, Eq)
instance Functor Box where
fmap f (Box x) = Box (f x)
-- Applicative instance
instance Applicative Box where
pure = Box
(Box f) <*> (Box x) = Box (f x)
-- Monad instance
instance Monad Box where
return = pure
(Box x) >>= f = f x
-- Using functor
doubleInBox :: Box Int -> Box Int
doubleInBox = fmap (*2)
-- Using applicative
applyInBox :: Box (Int -> Int) -> Box Int -> Box Int
applyInBox f x = f <*> x
-- Using monad
chainBox :: Box Int -> Box Int
chainBox x = x >>= \n -> Box (n + 1)
Type Families and GADTs
Example:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
module Advanced where
-- Type families
type family Element c where
Element [a] = a
Element (Maybe a) = a
headElement :: [a] -> Element [a]
headElement (x:_) = x
headElement [] = error "empty list"
-- Data families
data family Array e
data instance Array Int = IntArray [Int]
data instance Array Bool = BoolArray [Bool]
-- GADTs (Generalized Algebraic Data Types)
data Expr a where
IntLit :: Int -> Expr Int
BoolLit :: Bool -> Expr Bool
Add :: Expr Int -> Expr Int -> Expr Int
Equals :: Expr Int -> Expr Int -> Expr Bool
If :: Expr Bool -> Expr a -> Expr a -> Expr a
eval :: Expr a -> a
eval (IntLit n) = n
eval (BoolLit b) = b
eval (Add x y) = eval x + eval y
eval (Equals x y) = eval x == eval y
eval (If cond t e) = if eval cond then eval t else eval e
Recursive Data Structures
Example:
module Recursion where
-- Binary tree
data Tree a = Empty
| Node a (Tree a) (Tree a)
deriving (Show, Eq)
-- Insert into binary search tree
insert :: Ord a => a -> Tree a -> Tree a
insert x Empty = Node x Empty Empty
insert x (Node y left right)
| x < y = Node y (insert x left) right
| x > y = Node y left (insert x right)
| otherwise = Node y left right
-- Tree traversal
inorder :: Tree a -> [a]
inorder Empty = []
inorder (Node x left right) = inorder left ++ [x] ++ inorder right
-- Find in tree
findTree :: Ord a => a -> Tree a -> Bool
findTree _ Empty = False
findTree x (Node y left right)
| x == y = True
| x < y = findTree x left
| otherwise = findTree x right
-- Linked list (redundant with built-in lists, but for demonstration)
data List a = Nil | Cons a (List a)
deriving (Show, Eq)
listMap :: (a -> b) -> List a -> List b
listMap _ Nil = Nil
listMap f (Cons x xs) = Cons (f x) (listMap f xs)
Lazy Evaluation and Infinite Lists
Example:
module Lazy where
-- Infinite list of natural numbers
naturals :: [Integer]
naturals = [0..]
-- Fibonacci sequence (infinite)
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
-- Prime numbers (Sieve of Eratosthenes)
primes :: [Integer]
primes = sieve [2..]
where
sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]
-- Take first n primes
firstNPrimes :: Int -> [Integer]
firstNPrimes n = take n primes
-- Cycle and repeat
repeatedPattern :: [Int]
repeatedPattern = cycle [1, 2, 3]
constantList :: Int -> [Int]
constantList x = repeat x
-- Lazy evaluation in action
ones :: [Integer]
ones = 1 : ones
-- Take elements while condition holds
takeWhileLessThan :: Int -> [Int] -> [Int]
takeWhileLessThan n = takeWhile (< n)