Haskell's type system is one of its greatest strengths — types describe exactly what a function does, and the compiler enforces those contracts.
Sum types (OR)
HASKELL
data Color = Red | Green | Blue | Yellow
-- Pattern matching on custom types
describe :: Color -> String
describe Red = "Red as the sun"
describe Green = "Green as the hills"
describe Blue = "Blue as the sky"
describe Yellow = "Yellow as the marigold"Product types (AND)
HASKELL
data Point = Point Double Double
origin :: Point
origin = Point 0 0
distance :: Point -> Point -> Double
distance (Point x1 y1) (Point x2 y2) =
sqrt ((x2 - x1)^2 + (y2 - y1)^2)Combined (most useful)
HASKELL
data Shape
= Circle Double -- radius
| Rectangle Double Double -- width, height
| Triangle Double Double Double -- sides
area :: Shape -> Double
area (Circle r) = pi * r * r
area (Rectangle w h) = w * h
area (Triangle a b c) =
let s = (a + b + c) / 2
in sqrt (s * (s-a) * (s-b) * (s-c))Maybe — Replacing null
HASKELL
data Maybe a = Just a | Nothing
safeDivide :: Double -> Double -> Maybe Double
safeDivide _ 0 = Nothing
safeDivide a b = Just (a / b)
-- Using Maybe
case safeDivide 10 0 of
Nothing -> putStrLn "Cannot divide by zero"
Just res -> putStrLn ("Result: " ++ show res)Type classes
Type classes are Haskell's mechanism for ad-hoc polymorphism (like interfaces):
HASKELL
-- The Eq type class requires ==
class Eq a where
(==) :: a -> a -> Bool
-- The Show type class requires a string representation
class Show a where
show :: a -> String
-- Deriving common type classes
data Student = Student
{ name :: String
, grade :: Char
} deriving (Show, Eq)
-- Now you can use:
-- show (Student "Ram" 'A') == "Student {name = \"Ram\", grade = 'A'}"
-- Student "Ram" 'A' == Student "Sita" 'B' -- FalseParameterized types
HASKELL
data Result a = Success a | Error String
resultToString :: Result Int -> String
resultToString (Success n) = "Got: " ++ show n
resultToString (Error msg) = "Error: " ++ msgTips
- Use sum types for things that can be one of several variants.
- Use
Maybeinstead of null — the compiler forces you to handle the Nothing case. - Use
derivingto auto-generate common type class instances. - Types are your documentation — make them expressive.
Next: fp.