CodeToLive

Types & Typeclasses in Haskell

Haskell has a powerful static type system that helps catch errors at compile time. Understanding types and typeclasses is essential for writing correct and expressive Haskell code.

Basic Types

Haskell comes with several built-in types:


-- Boolean
isTrue :: Bool
isTrue = True

-- Characters
firstLetter :: Char
firstLetter = 'A'

-- Numbers
integer :: Integer  -- Arbitrary precision
integer = 12345678901234567890

int :: Int          -- Fixed precision (machine-dependent)
int = 42

double :: Double
double = 3.14159

float :: Float
float = 2.71828

-- Strings (which are lists of characters)
greeting :: String
greeting = "Hello, Haskell!"
      

Type Signatures

Explicit type signatures document functions and help catch errors:


-- Function with type signature
add :: Int -> Int -> Int
add x y = x + y

-- Without type signature (Haskell can infer)
add x y = x + y
      

Type Inference

Haskell can often infer types without explicit annotations:


-- Haskell infers the most general type
identity x = x  -- identity :: a -> a

-- Const function
const x y = x   -- const :: a -> b -> a
      

Type Variables

Type variables enable polymorphic functions:


-- Polymorphic identity function
id :: a -> a
id x = x

-- First element of a list
head :: [a] -> a
head (x:_) = x
      

Typeclasses

Typeclasses define interfaces for sets of types:


-- Eq typeclass (for equality)
data Color = Red | Green | Blue

instance Eq Color where
  Red == Red = True
  Green == Green = True
  Blue == Blue = True
  _ == _ = False

-- Show typeclass (for string representation)
instance Show Color where
  show Red = "Red"
  show Green = "Green"
  show Blue = "Blue"
      

Common Typeclasses

Some important built-in typeclasses:


-- Eq (equality)
class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool

-- Ord (ordering)
class Eq a => Ord a where
  compare :: a -> a -> Ordering
  (<), (<=), (>), (>=) :: a -> a -> Bool
  max, min :: a -> a -> a

-- Show (string representation)
class Show a where
  show :: a -> String

-- Read (parsing from string)
class Read a where
  read :: String -> a

-- Num (numeric operations)
class Num a where
  (+), (-), (*) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
      

Creating Custom Types

Haskell provides several ways to define new types:


-- Type synonyms (aliases)
type Name = String
type Age = Int
type Person = (Name, Age)

-- Newtype (wrapper with no runtime overhead)
newtype Meter = Meter Double

-- Data types
data Shape = Circle Double | Rectangle Double Double

-- Record syntax
data Person = Person {
  name :: String,
  age :: Int,
  email :: String
}
      

Algebraic Data Types

ADTs are a powerful feature of Haskell's type system:


-- Simple ADT
data Bool = False | True

-- ADT with parameters
data Maybe a = Nothing | Just a

-- Recursive ADT
data List a = Empty | Cons a (List a)

-- ADT with multiple constructors
data Expr = 
    Lit Int
  | Add Expr Expr
  | Mul Expr Expr
  | Var String
      

Type Parameters

Types can be parameterized by other types:


-- Parameterized type
data Box a = Box a

-- Parameterized function
unwrap :: Box a -> a
unwrap (Box x) = x

-- Parameterized type with constraints
maximum :: Ord a => [a] -> a
maximum [] = error "empty list"
maximum [x] = x
maximum (x:xs) = max x (maximum xs)
      
← Previous: Functions & Recursion | Next: Pattern Matching →