Reading — step 1 of 7
Learn
Functions are first-class in OCaml. Pass them around, return them, store them — the foundation of functional style.
Functions as values
let double x = x * 2
let f = double (* alias the function *)
let () = Printf.printf "%d\n" (f 5) (* 10 *)
Functions have types like values: double : int -> int.
Anonymous functions (lambdas)
let f = fun x -> x * 2
let g = fun x y -> x + y
fun args -> body. Multi-arg lambdas can be written fun x y -> ... (which is really fun x -> fun y -> ... — currying).
Currying — partial application
All OCaml functions are curried by default:
let add x y = x + y (* int -> int -> int *)
let add5 = add 5 (* int -> int — partially applied *)
let () = Printf.printf "%d\n" (add5 10) (* 15 *)
Calling add 5 with only one argument returns a function expecting the second. No special syntax needed — just call with fewer args.
map, filter, fold
List.map (fun x -> x * 2) [1; 2; 3] (* [2; 4; 6] *)
List.filter (fun x -> x > 2) [1; 2; 3; 4] (* [3; 4] *)
List.fold_left (+) 0 [1; 2; 3] (* 6 *)
List.fold_left (fun acc x -> x :: acc) [] [1; 2; 3] (* [3; 2; 1] — manual reverse *)
Pipe operator |> — readable pipelines
let result =
[1; 2; 3; 4; 5]
|> List.filter (fun x -> x mod 2 = 1)
|> List.map (fun x -> x * x)
|> List.fold_left (+) 0
(* 1*1 + 3*3 + 5*5 = 35 *)
x |> f is f x. Chains of single-arg applications read top-to-bottom. Idiomatic for pipelines.
Function composition
let (>>) f g x = g (f x)
let pipeline = (fun x -> x + 1) >> (fun x -> x * 2) >> string_of_int
let () = print_endline (pipeline 5) (* "12" *)
No built-in compose operator in stdlib — define it or use Fun.compose from the stdlib (recent versions).
Useful higher-order helpers
Fun.id x (* x — identity *)
Fun.const 42 x (* 42 — constant function *)
Fun.flip f a b (* f b a — argument swap *)
List.iter print_int [1; 2; 3]
List.exists (fun x -> x > 5) [1; 2; 3] (* false *)
List.for_all (fun x -> x > 0) [1; 2; 3] (* true *)
List.find (fun x -> x > 2) [1; 2; 3] (* 3; throws if no match *)
List.find_opt (fun x -> x > 5) [1; 2; 3] (* None *)
Common mistakes
- Using
==for function equality — function equality is undefined / generally false; comparing functions doesn't make sense. - Forgetting
|>— newcomers write nested calls. The pipe makes flow obvious. - Currying surprise —
add 5returns a function. If you meant to call it, you forgot the second arg. funarity confusion —fun x y -> ...is two-arg.fun (x, y) -> ...takes a TUPLE.- Reaching for compose when pipe works — for value flow, pipe. compose is for building reusable compositions.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…