필사 모드: Functional + BEAM + Emerging Languages 2026 Deep Dive — Elixir 1.18, Phoenix LiveView 1.1, Gleam, Erlang/OTP 28, Haskell GHC 9.12, OCaml 5.x, Scala 3, Clojure, Roc, Lean 4
EnglishIn 2026, functional programming is no longer "an academic luxury." Elixir, paired with Phoenix LiveView 1.1, has carved a foothold against SSR React at KakaoBank, Toss, and elsewhere; Gleam has exploded in popularity since 1.6 as the "typed BEAM" language; Haskell remains rock-solid for finance, compilers, and blockchain with GHC 9.12; and OCaml 5.x has finally delivered a stable multicore runtime that is pushing beyond Jane Street into mainstream backends. This piece walks through Erlang/OTP 28, F# 9, Scala 3, Clojure 1.13, plus Roc, Lean 4, Unison, Idris 2, and Koka — the entire 2026 functional landscape in one breath.
Why Functional, Again — The 2026 Current
The LLM era brought a curious shift. As code-generation tools went mainstream, the value of "code easy for humans to debug" was overtaken by "code the type system catches." The verifiability of Haskell, OCaml, Rust, and Gleam, combined with BEAM's fault tolerance, is being re-evaluated as a safety net against the micro-bugs LLM boilerplate produces.
The other current is concurrency. As core counts climb, GIL-based languages (Python, Ruby) are working to remove their GILs but still have a long road ahead, and the goroutine model has accumulated subtle deadlock issues around channels and mutexes. Erlang/BEAM's actor model, OCaml 5's effect-handler parallelism, Haskell's STM, Scala's ZIO and Cats Effect — functional concurrency models are once again first-class choices in 2026.
Elixir 1.18 — The Set-Theoretic Types Preview Lands
Released in late 2025, Elixir 1.18 doubled down on the set-theoretic types preview led by José Valim and Guillaume Duboc. Even without type annotations on function signatures, the compiler analyzes call sites to infer union types. Unlike Dialyzer, it works incrementally and integrates much more smoothly with IDEs.
defmodule Account do
defstruct [:id, :balance]
@spec withdraw(%Account{}, pos_integer()) ::
{:ok, %Account{}} | {:error, :insufficient_funds}
def withdraw(%Account{balance: balance} = acc, amount)
when balance >= amount do
{:ok, %{acc | balance: balance - amount}}
end
def withdraw(_acc, _amount), do: {:error, :insufficient_funds}
end
The return type of `withdraw/2` is the sum `{:ok, %Account{}}` or `{:error, :insufficient_funds}`. The 1.18 inferencer warns when callers ignore the failure branch. Pair it with `mix compile --warnings-as-errors` in CI and you have a strong net.
Phoenix 1.8 + LiveView 1.1 — SSR Meets Real Time
Phoenix 1.8 shipped alongside LiveView 1.1, and the headline changes were the stabilization of the streams API and proper backpressure for async assigns. Sending server-rendered HTML diffs over WebSockets solves what React Server Components tried to solve, but with a much simpler mental model.
defmodule MyAppWeb.OrdersLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
Phoenix.PubSub.subscribe(MyApp.PubSub, "orders")
{:ok, stream(socket, :orders, MyApp.Orders.recent())}
end
def handle_info({:new_order, order}, socket) do
{:noreply, stream_insert(socket, :orders, order, at: 0)}
end
def handle_event("cancel", %{"id" => id}, socket) do
case MyApp.Orders.cancel(id) do
{:ok, order} ->
{:noreply, stream_delete(socket, :orders, order)}
{:error, reason} ->
{:noreply, put_flash(socket, :error, "cancel failed: #{inspect(reason)}")}
end
end
end
LiveView's real power is that this single file handles SSR, real-time push, and optimistic UI updates. PubSub layered over Phoenix Channels scales naturally across nodes. That is why KakaoBank moved parts of its back office to LiveView — dozens of operators share the same screen in real time without a separate React+WebSocket build.
OTP Patterns — Supervisor, GenServer, ETS, Mnesia
Elixir and Erlang shine through OTP (Open Telecom Platform). Supervisors manage child processes with policies (`one_for_one`, `rest_for_one`, `one_for_all`), GenServers encapsulate state, ETS gives in-memory key-value storage, and Mnesia layers ACID and distribution on top of ETS.
defmodule MyApp.RateLimiter do
use GenServer
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def init(_opts) do
:ets.new(:rate_limits, [:set, :public, :named_table])
{:ok, %{}}
end
def allow?(key, limit, window_ms) do
now = System.monotonic_time(:millisecond)
case :ets.lookup(:rate_limits, key) do
[{^key, count, window_start}] when now - window_start < window_ms ->
if count < limit do
:ets.insert(:rate_limits, {key, count + 1, window_start})
true
else
false
end
_ ->
:ets.insert(:rate_limits, {key, 1, now})
true
end
end
end
ETS gives microsecond reads, and Mnesia optionally replicates across data centers. In 2026 the half-joke "Elixir plus OTP gives you Postgres, Redis, and RabbitMQ in one runtime" still has truth to it for small teams.
Broadway + Oban + Ash Framework
Broadway is a data-pipeline library that consumes Kafka, SQS, and RabbitMQ messages with batch processing. Oban is a Postgres-backed background job queue with cron, priorities, and retry policies. Ash Framework is a declarative metaprogramming stack that generates GraphQL, REST, and admin UI from resource declarations.
defmodule MyApp.Resources.User do
use Ash.Resource,
data_layer: AshPostgres.DataLayer
attributes do
uuid_primary_key :id
attribute :email, :string, allow_nil?: false
attribute :name, :string
timestamps()
end
actions do
defaults [:read, :update, :destroy]
create :register do
accept [:email, :name]
change MyApp.Changes.HashPassword
end
end
policies do
policy action_type(:read) do
authorize_if expr(id == ^actor(:id))
end
end
end
Ash has become the declarative full-stack tool of choice, and in 2026 integration with LiveView is tighter than ever. The admin UI ash_admin generates can replace Retool-class SaaS for many teams.
Erlang/OTP 28 — Mature JIT and mTLS
Released in late 2025, Erlang/OTP 28 further polished BeamAsm JIT and brought ARM64 throughput up to x86 levels. mTLS and QUIC support are now deeper in the standard library, making inter-node communication safer. New Erlang projects are rare, but as the foundation of RabbitMQ, CouchDB, Riak, VerneMQ, and the WhatsApp backend, Erlang remains critical infrastructure.
-module(echo_server).
-behaviour(gen_server).
-export([start_link/0, echo/1, init/1, handle_call/3, handle_cast/2]).
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
echo(Msg) ->
gen_server:call(?MODULE, {echo, Msg}).
init([]) ->
{ok, #{count => 0}}.
handle_call({echo, Msg}, _From, State = #{count := N}) ->
{reply, {ok, Msg, N}, State#{count := N + 1}};
handle_call(_, _From, State) ->
{reply, {error, unknown}, State}.
handle_cast(_Msg, State) -> {noreply, State}.
Erlang's Prolog heritage shows in its dot/semicolon/comma punctuation, which gives a steep learning curve. But once internalized, every OTP design pattern applies directly.
Gleam 1.6+ — The Typed BEAM Star
By 2026 Gleam has marched from 1.6 to 1.10, becoming the only statically typed functional language that compiles to both the Erlang VM and JavaScript. Louis Pilfold is BDFL, and the syntax feels like a clean blend of Rust, Elm, and F#. OpenTelemetry support and the Lustre frontend framework make full-stack Gleam viable today.
pub type Order {
Order(id: Int, total: Float, status: Status)
}
pub type Status {
Pending
Paid
Shipped
Cancelled
}
pub fn settle(order: Order) -> Result(Order, String) {
case order.status {
Pending -> Ok(Order(..order, status: Paid))
Paid -> Ok(Order(..order, status: Shipped))
Shipped -> Error("already shipped")
Cancelled -> Error("cancelled order cannot proceed")
}
}
pub fn main() {
let orders = [
Order(1, 99.0, Pending),
Order(2, 49.5, Paid),
]
orders
|> list.map(settle)
|> list.each(io.debug)
}
Gleam's draw is keeping Erlang's actor model while gaining compile-time type checks. There is no Phoenix-class metaframework yet, but Lustre is filling that space quickly.
LFE (Lisp Flavored Erlang) — Small but Solid
LFE is a Lisp dialect on BEAM created by Robert Virding (co-creator of Erlang). It brings macros and homoiconicity to the BEAM the way Clojure did for the JVM. The user base is small, but OTP compatibility is perfect.
Haskell GHC 9.10/9.12 — Linear Types and GHC2024
GHC 9.10 and 9.12 made GHC2024 the default language edition, matured Linear Types, and significantly improved type-checker performance. Effect systems (effectful, Polysemy, Cleff) are rapidly displacing mtl-style code, and GHC's inference keeps getting better year over year.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
module Wallet where
data Wallet = Wallet
{ owner :: String
, balance :: Int
} deriving (Show)
data Tx
= Deposit Int
| Withdraw Int
deriving (Show)
apply :: Wallet -> Tx -> Either String Wallet
apply w (Deposit n)
| n > 0 = Right w { balance = balance w + n }
| otherwise = Left "deposit must be positive"
apply w (Withdraw n)
| n <= balance w = Right w { balance = balance w - n }
| otherwise = Left "insufficient funds"
settle :: Wallet -> [Tx] -> Either String Wallet
settle = foldl (\acc tx -> acc >>= flip apply tx) . Right
Haskell's lazy evaluation is still a double-edged sword, but IO isolation and a powerful type system are why Standard Chartered, Mercury, and Tweag run critical infrastructure on it. Cabal and Stack are both actively maintained, and in 2026 nix-flakes integration is essentially the norm.
OCaml 5.x — Multicore Unleashed
OCaml 5 introduced effect handlers and domain-based parallel GC. With 5.3 stabilized, multicore OCaml is finally real. Jane Street maintains its own oxcaml fork, but mainstream OCaml 5 is also potent.
open Effect
open Effect.Deep
type _ Effect.t += Read : string Effect.t
| Log : string -> unit Effect.t
let interact () =
let name = perform Read in
perform (Log ("hello, " ^ name));
perform (Log "bye")
let run program input =
try_with program ()
{ effc = fun (type a) (e: a Effect.t) ->
match e with
| Read -> Some (fun (k: (a, _) continuation) -> continue k input)
| Log msg -> Some (fun k -> print_endline msg; continue k ())
| _ -> None }
let () = run interact "youngju"
The snippet shows OCaml 5's effect handlers in action. Abstracting synchronous IO as effects and switching handler behavior is algebraic effects at its purest. Dune and opam have steadily matured, and melange remains the live option for OCaml-to-JS compilation.
ReScript — OCaml's JS-Friendly Branch
ReScript (formerly BuckleScript / Reason) wraps the OCaml type system in React-friendly syntax. ReScript 11/12 smoothed out the V11 migration and GenType integration. JavaScript-flavored keywords (`let`, `if`, `match`) combine with OCaml's powerful inference to write React components.
type user = {
id: int,
name: string,
email: option<string>,
}
let formatUser = (u: user) =>
switch u.email {
| Some(e) => `${u.name} <${e}>`
| None => `${u.name} (no email)`
}
@react.component
let make = (~user) =>
ReScript still differentiates with ultra-fast incremental compilation via fb-watchman even as Rome/Biome and others have appeared. In Japan, Money Forward has publicly shared ReScript adoption stories.
F# 9 + .NET 9 — The Enterprise Functional Standard
F# 9 on .NET 9 integrates nullable reference types, polishes computation expression performance, and stabilizes type providers. Jet.com was the canonical F# case study; in 2026, G-Research and Walmart use F# for data pipelines and trading infrastructure.
type Shape =
| Circle of radius: float
| Rectangle of width: float * height: float
| Triangle of a: float * b: float * c: float
let area shape =
match shape with
| Circle r -> System.Math.PI * r * r
| Rectangle (w, h) -> w * h
| Triangle (a, b, c) ->
let s = (a + b + c) / 2.0
sqrt (s * (s - a) * (s - b) * (s - c))
[<EntryPoint>]
let main _ =
[ Circle 1.0; Rectangle (3.0, 4.0); Triangle (3.0, 4.0, 5.0) ]
|> List.iter (fun s -> printfn "%A area=%.2f" s (area s))
0
F#'s strength is using the entire .NET ecosystem while writing in a functional style. ASP.NET Core, EF Core, and the Azure SDK all work naturally from F#.
Scala 3 + ZIO + Cats Effect — JVM Functional's Twin Pillars
Scala 3.6 polished enums, given/using instances, opaque type aliases, and extension methods. JVM functional libraries split between ZIO and Cats Effect, with ZIO 2 offering a throwable-free functional effect system. Akka, after its license change, is preserved in the Pekko fork.
object OrderService:
enum OrderError:
case NotFound, AlreadyPaid, InsufficientFunds
case class Order(id: Long, amount: BigDecimal, paid: Boolean)
trait OrderRepo:
def find(id: Long): IO[OrderError.NotFound.type, Order]
def save(order: Order): UIO[Unit]
def pay(id: Long): ZIO[OrderRepo, OrderError, Order] =
for
repo <- ZIO.service[OrderRepo]
order <- repo.find(id)
_ <- ZIO.fail(OrderError.AlreadyPaid).when(order.paid)
paid = order.copy(paid = true)
_ <- repo.save(paid)
yield paid
ZIO's `ZIO[R, E, A]` type exposes environment R, error E, and result A in the signature itself. Reading the signature alone tells you the dependencies and error variants — that is functional effect systems at their best.
Clojure 1.13 + ClojureScript + Babashka
Clojure 1.13 brought inline def, keyword arguments, and deps.edn refinements. ClojureScript remains active through both SCI (Small Clojure Interpreter) and Shadow CLJS, and Babashka has solidified its place as a single-binary Clojure for shell scripting. nbb is the Babashka of Node.js.
(ns billing.core
(:require [clojure.string :as str]))
(defn line-total [{:keys [qty unit-price discount]}]
(let [base (* qty unit-price)
amount (* base (- 1 (or discount 0)))]
(Math/round (double amount))))
(defn invoice [{:keys [customer items]}]
(let [lines (map line-total items)
subtotal (reduce + lines)
vat (Math/round (double (* subtotal 0.1)))]
{:customer customer
:subtotal subtotal
:vat vat
:total (+ subtotal vat)}))
(comment
(invoice {:customer "ACME"
:items [{:qty 3 :unit-price 9900}
{:qty 1 :unit-price 49000 :discount 0.1}]}))
Clojure's draws are REPL-driven development and immutable data structures. Babashka makes "Clojure instead of Python for small tools" a realistic option.
The BEAM Trio — Elixir vs Erlang vs Gleam
The three BEAM languages have diverged in the market. Elixir is the easiest entry for full-stack developers and a metaprogramming powerhouse, Erlang remains the heart of telco and messaging infrastructure, and Gleam appeals to a new generation that loves types.
- **Elixir**: Phoenix LiveView ecosystem, Mix builds, OTP patterns, set-theoretic types preview
- **Erlang**: massive infrastructure such as WhatsApp, RabbitMQ, and Riak, rebar3 builds, classic OTP
- **Gleam**: Rust-flavored syntax, complete type safety, Erlang and JS targets, Lustre frontend
All three interop freely within the same VM. Calling Erlang libraries from Elixir or Gleam modules from Elixir is increasingly common.
The ML Family — OCaml vs F# vs ReScript
Same ML lineage, distinct domains.
- **OCaml**: compilers, static analysis, Jane Street trading, Dune builds, opam packaging
- **F#**: .NET ecosystem integration, cross-platform via the dotnet CLI
- **ReScript**: frontend React/Next.js compile target, npm friendly, GenType
OCaml has a very light memory model and fast compilation. F# inherits the .NET stack wholesale. ReScript produces small JS bundles.
Roc — A Rust-Spirited Functional Language
Created by Richard Feldman (an Elm core contributor), Roc aims to bring "the spirit of Rust" to functional programming. It is in beta in 2026, but the compilation speed and runtime efficiency are impressive. Its platform abstraction lets the same Roc code deploy to CLI, WebAssembly, and Lambda.
Lean 4 — From Theorem Prover to General Language
Lean 4 is both a theorem prover and a functional language, driven by Leonardo de Moura at Microsoft Research. The explosive growth of mathlib and Terence Tao's 2024 collaboration cemented it as a serious academic tool. By 2026, Lean 4 is also being used as a general-purpose language for compilers and DSLs.
Unison — Content-Addressed Code
Unison identifies functions by the hash of their body. Imports disappear, dependency resolution lives in the compiler, and renames are mere metadata updates. The stabilization of Unison Share in 2026 has kicked off serious experimentation with "code sharing without Git."
Idris 2 + Koka — Next-Gen Types and Effects
Idris 2 is an ML successor centered on dependent types, and Koka is an effect-typed language from Microsoft Research. Both lean academic but directly influenced OCaml 5's effect handlers, Haskell effect libraries, and Scala's ZIO.
Korea and Japan Adoption
In Korea, KakaoBank has presented at conferences about running parts of its back office on Elixir and Phoenix LiveView, and Toss frequently publishes Elixir/OTP study posts on its tech blog. In Japan, Cookpad has shared a migration from Ruby to Elixir for some services, and LINE has long used Erlang/OTP in game backends. Erlang Solutions runs a Tokyo office and regularly sponsors Code BEAM conferences.
A Suggested Learning Path
If you are new to functional programming, learning OTP through Elixir is the most welcoming entry. From there, take Gleam or OCaml 5 if you crave more types, and graduate to Haskell or Scala for deeper abstractions. Save Lean 4 and Idris 2 for last. F# is the fastest on-ramp if you already know .NET. Clojure is the top pick if you love REPLs and immediate feedback.
A Functional Library Matrix
A one-liner per language for the canonical libraries.
- Elixir: Phoenix, LiveView, Ecto, Broadway, Oban, Ash, Nx (numerical)
- Erlang: Cowboy, RabbitMQ, Riak, VerneMQ, ranch, lager
- Gleam: gleam_otp, gleam_http, lustre, mist, wisp
- Haskell: servant, persistent, optics, conduit, megaparsec, polysemy, effectful
- OCaml: dune, opam, lwt, async, owl (numerical), bonsai (UI), melange
- F#: Giraffe, Saturn, FsToolkit.ErrorHandling, FParsec, Fable
- Scala 3: ZIO, Cats Effect, http4s, Doobie, Tapir, Akka/Pekko
- Clojure: Reagent, re-frame, malli, integrant, mount, next.jdbc
These are the de-facto standards or near-standards in each language.
Wrap-Up — Functional Is a Tool, Not a Luxury
In 2026, functional programming is no longer "preference" or "academic luxury." Elixir and Gleam wrap BEAM's solidity in modern DX, OCaml 5 has unlocked its multicore potential, and Scala, F#, and Haskell hold their own as industry-standard tools in their respective niches. As the LLM era makes verifiability matter again, weaving one or two functional tools into your stack becomes a long-term safety asset for your team.
References
- elixir-lang.org
- phoenixframework.org
- gleam.run
- www.erlang.org
- www.haskell.org
- ocaml.org
- fsharp.org
- scala-lang.org
- clojure.org
- roc-lang.org
- lean-lang.org
- www.idris-lang.org
- koka-lang.github.io
- unison-lang.org
현재 단락 (1/281)
In 2026, functional programming is no longer "an academic luxury." Elixir, paired with Phoenix LiveV...