Dive C1.04.2
Function composition
Glue two functions into one — double >> inc is a single function, no value in sight.
Where the pipe threads a value you already hold, composition
>> builds a new function out of two existing ones, to use later. By definition
let (>>) f g x = g (f x), so f >> g is the function
fun x -> g (f x): run f first, hand its output to
g. It runs left first — double >> inc
doubles, then increments. The payoff is point-free definitions: name the combined
function and never mention its argument. This dive defines >>, contrasts it
with the pipe, and adds the backward composition <<.
One function out of two
Composition is another ordinary operator from FSharp.Core, defined in one line.
It takes two functions f and g and returns a function that
applies f first and feeds the result to g. The result is a
value of function type — bind it to a name and it is usable on its own.
// from FSharp.Core — the whole definition let (>>) f g x = g (f x) let double x = x * 2 // val double : int -> int let inc x = x + 1 // val inc : int -> int let f = double >> inc // val f : (int -> int) — double then inc f 5 // val it : int = 11 let g = inc >> double // inc then double g 5 // val it : int = 12 == double (inc 5)
The order matters: f and g use the same two functions but
in opposite order, and they give 11 and 12.
double >> inc applied to 5 is
inc (double 5) = inc 10 = 11; inc >> double is
double (inc 5) = double 6 = 12. The left function in the >>
always runs first.
- >>
- composition:
(f >> g)isfun x -> g (f x). The left function runs first. - (int -> int)
double >> incis a value of function type; the F# Interactive prints it in parentheses.- order
double >> incdoubles then increments;inc >> doublereverses it.- point-free
- the definition
let f = double >> incnames the combined function and mentions no argument.
Thread a value, or fuse the functions
The pipe and composition reach the same 11 by different routes. Switch between the
two views: the pipe view threads the value 5 through
double then inc; the compose view fuses the
two boxes into one function f = double >> inc and applies it to
5. The pipe needs the value present; composition builds the function first.
double then inc · two ways to the same 11
View A · pipe threads the value
View B · compose fuses the functions
Same two functions, same 11. The pipe runs the steps on a value in hand;
composition packages the steps into one function for whenever a value arrives.
The pipe
Needs a value now: 5 |> double |> inc threads what you already hold.
Composition
Builds a function for later: double >> inc names no value at all.
The backward composition <<
Composition has a reverse, <<, which runs the right function
first: (g << f) is fun x -> g (f x). It reads the way
the nested-call form reads, with the outermost function written first. So
inc << double is the same function as double >> inc —
double first, then increment.
// from FSharp.Core let (<<) g f x = g (f x) let h = inc << double // val h : (int -> int) — double first, then inc h 5 // val it : int = 11 == (double >> inc) 5
The forward composition >> matches the left-to-right reading of the pipe and is
the one F# code uses most. The backward << reads like mathematics, where
g ∘ f means "apply f, then g". Both
define the same kind of function; the choice is which reading order suits the line.
Where this leads
A composition of two functions is a function; a composition of many is still one function. The next dive
puts both operators to work on real data: a pipeline that chains the collection functions with
|>, and the same pipeline named point-free with >>.
That is the shape every later module reuses.
References
Sources
- Microsoft — F# documentation — function composition and the composition operators.
- FSharp.Core API reference —
(>>)and(<<)in theOperatorsmodule. - The F# Language Specification — operator definitions, function types, and associativity.
Related in this course
- C1.04.3 — Building pipelines — composition put to work as a named pipeline.
- C1.04.1 — The pipe operator — the value-threading counterpart.
- Elixir — Composition — composing functions on the BEAM.