A Functional Programming Crash Course
Use Arrow Keys to navigate • Interactive playgrounds throughout
Functional programming mirrors mathematical reasoning
In Java/Python, you write instructions. In OCaml, you write definitions — just like math. let f x = x + 1 reads like "f(x) = x + 1".
OCaml has an interactive toplevel — type expressions, see results instantly
In the REPL, ;; tells OCaml "evaluate this now." In files, it's optional (and usually omitted).
OCaml won't convert int to float automatically. Use float_of_int, int_of_float, etc.
Even arithmetic differs: + for ints, +. for floats!
3 + 4;; → int arithmetic"hello" ^ " world";; → string concattrue && false;; → boolean logiclet x = 42;; → bindingOCaml is statically typed — every expression has a type known at compile time
| Type | Example | Operations |
|---|---|---|
int | 42, -7, 0 | +, -, *, /, mod |
float | 3.14, 2.0 | +., -., *., /. |
bool | true, false | &&, ||, not |
char | 'a', 'Z' | Char.code |
string | "hello" | ^, String.length |
unit | () | (side effects) |
3 + 4 is int addition. 3.0 +. 4.0 is float addition. Mixing them is a type error.
Binding names to values — NOT variable assignment!
let x = 10 means "x is 10" — not "store 10 in a box called x." You're creating a new name in the environment.
When you write let x = 20 after let x = 10, the old x still exists — it's just hidden ("shadowed"). Any code that captured the old x still sees 10.
let a = 5 in a + 1 means "in the expression a+1, let a be 5." The binding only lives inside the in expression.
Functions are values — define them, pass them, return them
let add x y = x + y is actually syntactic sugar for a function that takes x and returns another function that takes y.
Type: int -> int -> int = int -> (int -> int)
Named after Haskell Curry. A 2-argument function is really a 1-argument function that returns a 1-argument function. This enables partial application.
f x y not f(x, y). Parentheses are only for grouping: f (g x) means "apply g to x, then apply f to the result."
OCaml figures out the types — you rarely write them
OCaml uses constraint-based inference. It looks at how values are used and deduces their types. No annotations needed!
'a -> 'a means "takes any type, returns the same type." Like Java generics but inferred automatically.
In OCaml, if-then-else RETURNS a value — it's an expression, not a statement
Unlike Java/Python where if is a statement, in OCaml it's an expression that produces a value. Like the ternary ? : in Java, but this is the ONLY if.
If the then branch is string, the else branch must also be string. OCaml enforces this at compile time.
In functional programming, recursion replaces iteration entirely
Grouping related values together
(3, 7) is a point. The position matters, the name doesn't.
{ s with year = 4 } creates a new record — s is unchanged. This is how functional programming avoids side effects.
Singly-linked, immutable, homogeneous
Test your understanding of recursion and lists
@ operator appends two lists. What does placing h at the end of the recursive result do?
Destructure data and branch in one elegant construct
Define your own types with multiple cases — OCaml's killer feature
Pentagon), the compiler will warn you about every match that doesn't handle it. No forgotten cases, no null pointer exceptions.
This function has a subtle pattern matching error
h :: t, h is the first element (a value) but t is the rest of the list (still a list!). They have different types.
OCaml's elegant solution to the "billion-dollar mistake"
None. In Java, you can call .toString() on null and get a runtime crash. In OCaml, that's a compile error.
option instead — it makes failure explicit in the type.
Functions that take functions as arguments or return functions
add1 is a value just like 42. You can pass it around, store it, return it.
Three higher-order functions that replace most loops
|> let you express complex data transformations as clear, readable pipelines — no mutable variables, no loop counters.
Which higher-order function should you use?
"Given [1;2;3], produce [2;4;6]"
"Given [1;2;3;4], produce 10"
"Given [-1;2;-3;4], produce [2;4]"
Types that reference themselves — the foundation of tree structures
tree function matches Leaf (base) and Node (recurse on left/right).
How OCaml connects to CS305 and the bigger picture
let x = 5let f x = x+1fun x -> x+1let rec f n = ...match x withtype t = A | Bh :: tx |> f |> gList.map f lstList.fold_leftNone | Some v(a, b, c)fun x -> xList.map?let (a,_,c) = (1,2,3)What are a and c?
What does this function return?
What does this pipeline produce?