jonnifyfsharp

Chapter C3

F# for Elixir developers

You already think functionally. This chapter maps what you know onto a typed runtime.

If you write Elixir, F# will feel familiar long before it feels foreign: immutability by default, pattern matching, and the very same |> pipe. This chapter is the Elixir-community parallel to C2 · F# for C# developers — it takes each habit you carry from the BEAM and shows its idiomatic F# form on the CLR. The genuine shift is the type system: F# infers a static type for everything and checks your matches for exhaustiveness. Nine modules, three dives each.

The same ideas, a typed home

Elixir and F# are both functional-first languages with immutable data, first-class functions, and pattern matching at the centre. Elixir runs on the BEAM and stays dynamically typed; F# runs on the .NET CLR and is statically typed with full inference. So most of the vocabulary transfers directly — and where it changes, the change is usually the compiler doing more for you.

Select a concept below to see it both ways: the Elixir you would write, beside its idiomatic F# form. Both snippets are real and runnable. The full module directory follows.

The bridge · select a concept

Elixir · BEAM dynamic F# · CLR static, inferred the pipe |>

Elixir

# Elixir
[1, 2, 3, 4, 5]
|> Enum.map(fn x -> x * 2 end)
|> Enum.sum()
# => 30

F#

// F#
[ 1; 2; 3; 4; 5 ]
|> List.map (fun x -> x * 2)
|> List.sum
// val it : int = 30
The pipe |> is identical in both languages. Elixir's Enum becomes F#'s List (or Seq); the capture &(&1 * 2) becomes a lambda (fun x -> …).

Coming from Elixir, the surprise is how little is new — and that the new part, static types, mostly shows up as the compiler catching what you would have caught in a test.

The nine modules

Each module takes one Elixir habit and lands it in F#, three dives at a time. The last is a hands-on lab: a first .NET app, end to end.

live chapter front door built lesson ready soon specified
C3.01built

Two functional runtimes — the BEAM & the CLR

What carries over from the BEAM, and what the managed runtime changes.

C3.02built

From dynamic to static types

Type inference, and making illegal states unrepresentable.

C3.03built

Pattern matching, sharpened

Familiar ground, plus exhaustiveness and active patterns.

C3.04soon

The pipe you already know (+ composition)

The same |>, plus forward composition >>.

C3.05soon

Tuples & atoms → records & unions

Typed product and sum types for tuples and atoms.

C3.06soon

{:ok, _} / {:error, _} → Result & Option

The tagged tuples you return, as types.

C3.07soon

Processes & GenServer → MailboxProcessor

F#’s actor, async workflows, and what OTP adds.

C3.08soon

Protocols & behaviours → interfaces

Interfaces and object expressions for protocols.

C3.09soon

Mix & OTP → dotnet & .NET

A lab: the dotnet CLI, project structure, a first app.

References

Sources

Related in this course