SlideShare a Scribd company logo
Functional Design Patterns
Tomasz Kowal
Why this talk?
Why this talk?
Syntax
Pattern matching
and pin operator
Basic recursion, map,
reduce, tail recursion
Concurrency,
distributed systems
Very basic functional design patterns
Very basic functional design patterns
Very basic functional design patterns
Very basic functional design patterns
Why this talk?
Syntax
Pattern matching
and pin operator
Basic recursion, map,
reduce, tail recursion
Concurrency,
distributed systems
Very basic functional design patterns
Very basic functional design patterns
Why this talk?
Syntax
Pattern matching
and pin operator
Basic recursion, map,
reduce, tail recursion
How do I build stuff?
Questions
Please ask during the talk!
1 + 1
Very basic functional design patterns
Patterns
1. Use single data structure that is your single
source of truth and many small functions
operating on it.
2. Separate pure and impure parts.
Pipe operator
two = double(1)
two =
1
|> double()
Pipe operator
five = add(2, 3)
five =
2
|> add(3)
Pipe operator
one = 1
two = double(one)
four = double(two)
1
|> double()
|> double()
Pipe operator
list = [1, 10, 3, 12, 42]
Pipe operator
list = [1, 10, 3, 12, 42]
filtered = Enum.filter(
list,
&Integer.is_even/1
)
Pipe operator
list = [1, 10, 3, 12, 42]
filtered = Enum.filter(
list,
&Integer.is_even/1
)
sorted = Enum.sort(filtered)
Pipe operator
sorted =
list
|> Enum.filter(&Integer.is_even/1)
|> Enum.sort()
Pipe operator
sorted =
list
|> Enum.filter(&Integer.is_even/1)
|> Enum.sort()
sorted = Enum.sort(Enum.filter(list,
&Integer.is_even/1))
Pipe operator
def sorted_evens(list) do
list
|> Enum.filter(&Integer.is_even/1)
|> Enum.sort()
end
Pipe operator
def two_smallest_evens(list) do
list
|> sorted_evens()
|> Enum.take(2)
end
list list list
transform
list list list
transform
„Debugging” with IO.inspect
def two_smallest_evens(list) do
list
|> sorted_evens()
|> IO.inspect()
|> Enum.take(2)
end
Data validation problem
● Current value:
%User{name: „Tom”, age: 29}
● Things that we want to change:
%{age: 30}
● Is the data valid? If not – why?
Ecto.Changeset fields
● valid?
● data
● params
● changes
● errors
● ...
Validating with Ecto.Changeset
user
|> cast(params, [:name, :email, :age])
user changeset
cast
Validating with Ecto.Changeset
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
user changeset changeset
cast validate1
Validating with Ecto.Changeset
user
|> cast(params, [:name, :email, :age])
|> validate_required([:name, :email])
|> validate_format(:email, ~r/@/)
user changeset changeset changeset
cast validate1 validate2
Custom validator
● Lets say we have an event with start
date and end date.
● We want to make sure that start date is
not after end date.
Custom validator
def validate_interval(changeset, start, end)
do
end
Custom validator
def validate_interval(changeset, start, end) do
start_date = get_field(changeset, start)
end_date = get_field(changeset, end)
end
get_field
● Looks for value in params
● Looks for value in original data
Custom validator
def validate_interval(changeset, start, end) do
start_date = get_field(changeset, start)
end_date = get_field(changeset, end)
case Date.compare(start_date, end_date) do
:gt ->
_otherwise ->
end
end
Custom validator
def validate_interval(changeset, start, end) do
start_date = get_field(changeset, start)
end_date = get_field(changeset, end)
case Date.compare(start_date, end_date) do
:gt ->
_otherwise -> changeset
end
end
Custom validator
def validate_interval(changeset, start, end) do
start_date = get_field(changeset, start)
end_date = get_field(changeset, end)
case Date.compare(start_date, end_date) do
:gt -> add_error(changeset, start, "…")
_otherwise -> changeset
end
end
add_error
● appends new error to list of errors
● changes valid? to false
● takes changeset and returns changeset
Custom validator
def validate_interval(changeset, start, end) do
start_date = get_field(changeset, start)
end_date = get_field(changeset, end)
case Date.compare(start_date, end_date) do
:gt -> add_error(changeset, start, "…")
_otherwise -> changeset
end
end
Composing validators
def validate_address(cs, street, zip) do
cs
|> validate_street(street)
|> validate_zipcode(zip)
end
changeset changeset changeset
validate1
cs cs cs
v1
validate2
v2
Inserting to database
case Repo.insert(changeset) do
{:error, changeset} →...
{:ok, model} →...
end
Benefits
● Easy to compose: just |> another validator
● Easy to extend with custom validators
● Easy to test: all functions are pure
● Bonus: it works for any data.
Immutability digression
● Creating new structure every time is optimized
when language provides immutability
● list = [1, 2, 3]
1 2 3
Immutability digression
● Creating new structure every time is optimized
when language provides immutability
● list = [1, 2, 3]
● list2 = [0 | list]
0
1 2 3
Immutability digression
● Creating new structure every time is optimized
when language provides immutability
● list = [1, 2, 3]
● list2 = [0 | list]
● list3 = [4 | list]
0
4
1 2 3
Using Ecto.Multi
Multi.new
|> Multi.update(:account, a_changeset))
|> Multi.insert(:log, log_changeset))
|> Multi.delete_all(:sessions,
assoc(account, :sessions))
multi |> Repo.transaction
Composition
def extend_multi(multi, changeset) do
multi
|> Multi.insert(:some_tag, changeset)
end
multi multi multi
custom
multi multi multi
ins
insert
upd
How would you test this?
Repo.update(...)
Repo.insert(...)
Repo.delete_all(...)
Unit testing Ecto.Multi
assert [
{:account, {:update, achangeset, []}},
{:log, {:insert, log_changeset, []}},
{:sessions, {:delete_all, query, []}}
] = Ecto.Multi.to_list(multi)
Benefits
● Easy to compose: just |> another operation
● Easy to extend with Multi.run
● Easy to test with Multi.to_list
Garbage Collection digression
● Erlang GC is run separately for all processes
● When process dies, all its memory is freed
● This means that, if
– you use a process per request in your web
application and
– it has short lifecycle
The garbage collection may never happen!
Plug (or what makes Phoenix cool)
1. A specification for composable modules
between web applications
2. Connection adapters for different web
servers in the Erlang VM
Plug.Conn
● host
● method
● path_info
● req_headers
● params
● assigns
● resp_body
● status
A plug
def do_nothing(conn) do
conn
end
Pipeline
● Pipeline is a set of plugs
pipeline :pipeline_name do
plug :plug1
plug :plug2
end
● Pipeline is a plug
conn conn conn
pipeline
conn conn conn
v1
plug
v2
Almost the same...
def pipeline_name(conn) do
conn
|> if_not_halted(plug1)
|> if_not_halted(plug2)
end
The glue
def if_not_halted(conn, plug) do
if conn.halted? do
conn
else
plug(conn)
end
Phoenix is a pipeline
pipeline :phoenix do
plug :endpoint
plug :user_pipelines
plug :router
plug :controller
end
And lets you add custom plugs
def current_user(conn) do
account_id = get_session(conn, :account_id)
cond do
account = conn.assigns[:current_account] ->
conn
account = account_id && Repo.get(MyApp.Account, account_id) ->
assign(conn, :current_account, account)
true ->
assign(conn, :current_account, nil)
end
end
And lets you add custom plugs
def current_user(conn, repo  Repo) do
account_id = get_session(conn, :account_id)
cond do
account = conn.assigns[:current_account] ->
conn
account = account_id && repo.get(MyApp.Account, account_id) ->
assign(conn, :current_account, account)
true ->
assign(conn, :current_account, nil)
end
end
current_user test
defmodule Fakerepo do
def get(1) do
%Account{name: „Tomasz”, …}
end
end
current_user(conn, Fakerepo)
Benefits
● Easy to compose: set of plugs is a plug
● Easy to extend: your own plugs can be put
anywhere in the request cycle
● Easy to test: but you need to ensure explicit
contracts
Naming digression
● burritos
Naming digression
● burritos
● >>=
Naming digression
● burritos
● >>=
● Maybe, IO
Naming digression
● burritos
● >>=
● Maybe, IO
● A monad is just a monoid in the category of
endofunctors
GenServer
● GenServer abstracts an actor that takes
requests from the outside world and keeps
state.
c
c
server
c call
cast
cast
GenServer
def handle_call(msg, from, state) do
...
{:reply, actual_reply, new_state}
end
Benefits
● Easy to compose: not covered
● Easy to extend: just add another handle_call
● Easy to test: it is not even necessary to start it!
Elm Architecture
update
view
new_modelcommands
virtual dom
Browser with Elm
msgs model
Benefits
● Easy to compose: recursively
● Easy to extend: just add another message
● Easy to test: only pure functions!
Carrots
Did you know carrots are good for your
eyesight?
Very basic functional design patterns
Single source of truth
● Changeset
● Multi
● Plug.Conn
● GenServer’s State
● Elm Model
Separate pure and impure
● Keep impure parts separate from core logic
● Make impure parts as function inputs (explict
contracts)
Questions
If you like this talk, follow me on Twitter
@snajper47

More Related Content

What's hot (19)

PDF
How fast ist it really? Benchmarking in practice
Tobias Pfeiffer
 
PPTX
R programming
Pramodkumar Jha
 
PDF
c programming
Arun Umrao
 
PDF
Property-Based Testing
Shai Geva
 
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
ssuserd6b1fd
 
PDF
The underestimated power of KeyPaths
Vincent Pradeilles
 
PDF
Javascript
Vlad Ifrim
 
PDF
PythonOOP
Veera Pendyala
 
PDF
Pooya Khaloo Presentation on IWMC 2015
Iran Entrepreneurship Association
 
PDF
Protocols
SV.CO
 
PDF
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
ssuserd6b1fd
 
PDF
Introduction to python programming
Rakotoarison Louis Frederick
 
PDF
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
ssuserd6b1fd
 
PDF
Fog City Ruby - Triple Equals Black Magic
Brandon Weaver
 
PDF
Intro to OTP in Elixir
Jesse Anderson
 
PDF
The Magic Of Elixir
Gabriele Lana
 
PDF
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
ssuserd6b1fd
 
PPTX
Database performance 101
Leon Fayer
 
PDF
Tame cloud complexity with F#-powered DSLs
Yan Cui
 
How fast ist it really? Benchmarking in practice
Tobias Pfeiffer
 
R programming
Pramodkumar Jha
 
c programming
Arun Umrao
 
Property-Based Testing
Shai Geva
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 3 of 5 b...
ssuserd6b1fd
 
The underestimated power of KeyPaths
Vincent Pradeilles
 
Javascript
Vlad Ifrim
 
PythonOOP
Veera Pendyala
 
Pooya Khaloo Presentation on IWMC 2015
Iran Entrepreneurship Association
 
Protocols
SV.CO
 
Notes for C++ Programming / Object Oriented C++ Programming for MCA, BCA and ...
ssuserd6b1fd
 
Introduction to python programming
Rakotoarison Louis Frederick
 
Notes for C Programming for MCA, BCA, B. Tech CSE, ECE and MSC (CS) 5 of 5 by...
ssuserd6b1fd
 
Fog City Ruby - Triple Equals Black Magic
Brandon Weaver
 
Intro to OTP in Elixir
Jesse Anderson
 
The Magic Of Elixir
Gabriele Lana
 
Notes for GNU Octave - Numerical Programming - for Students - 02 of 02 by aru...
ssuserd6b1fd
 
Database performance 101
Leon Fayer
 
Tame cloud complexity with F#-powered DSLs
Yan Cui
 

Viewers also liked (12)

PDF
Tez: Accelerating Data Pipelines - fifthel
t3rmin4t0r
 
PDF
Elm: frontend code without runtime exceptions
Pietro Grandi
 
PDF
Claudia Doppioslash - Time Travel for game development with Elm
Codemotion
 
PDF
Elm a possible future for web frontend
Gaetano Contaldi
 
ODP
Elixir and elm - the perfect couple
Tomasz Kowal
 
PDF
Elm: delightful web development
Amir Barylko
 
PDF
Functional Web Development using Elm
💻 Spencer Schneidenbach
 
PDF
Rethink Frontend Development With Elm
Brian Hogan
 
PDF
A recommendation engine for your applications - M.Orselli - Codemotion Rome 17
Codemotion
 
PDF
Self-testing Code
Rogerio Chaves
 
PDF
Introduction to Elm
Rogerio Chaves
 
Tez: Accelerating Data Pipelines - fifthel
t3rmin4t0r
 
Elm: frontend code without runtime exceptions
Pietro Grandi
 
Claudia Doppioslash - Time Travel for game development with Elm
Codemotion
 
Elm a possible future for web frontend
Gaetano Contaldi
 
Elixir and elm - the perfect couple
Tomasz Kowal
 
Elm: delightful web development
Amir Barylko
 
Functional Web Development using Elm
💻 Spencer Schneidenbach
 
Rethink Frontend Development With Elm
Brian Hogan
 
A recommendation engine for your applications - M.Orselli - Codemotion Rome 17
Codemotion
 
Self-testing Code
Rogerio Chaves
 
Introduction to Elm
Rogerio Chaves
 
Ad

Similar to Very basic functional design patterns (20)

PDF
Elixir & Phoenix – fast, concurrent and explicit
Tobias Pfeiffer
 
PDF
Elixir & Phoenix – fast, concurrent and explicit
Tobias Pfeiffer
 
PDF
Functional programming with clojure
Lucy Fang
 
PDF
Beyond PITS, Functional Principles for Software Architecture
Jayaram Sankaranarayanan
 
PDF
Dont Drive on the Railroad Tracks
Eugene Wallingford
 
PDF
Functional Objects in Ruby: new horizons – Valentine Ostakh
Ruby Meditation
 
PDF
Micropatterns
cameronp
 
PDF
Pune Clojure Course Outline
Baishampayan Ghose
 
PDF
Functional programming in ruby
Koen Handekyn
 
PDF
Thinking Functionally - John Stevenson - Codemotion Rome 2017
Codemotion
 
PDF
Thinking Functionally with Clojure
John Stevenson
 
ODP
Clojure: Practical functional approach on JVM
sunng87
 
PDF
Elixir & Phoenix - fast, concurrent and explicit
Tobias Pfeiffer
 
PPT
Clojure 1a
Krishna Chaytaniah
 
PDF
Funtional Ruby - Mikhail Bortnyk
Ruby Meditation
 
PDF
Functional Ruby
Amoniac OÜ
 
PPTX
Esoteric LINQ and Structural Madness
Chris Eargle
 
PDF
Taking Inspiration From The Functional World
Piotr Solnica
 
PPTX
Clojure 7-Languages
Pierre de Lacaze
 
KEY
(map Clojure everyday-tasks)
Jacek Laskowski
 
Elixir & Phoenix – fast, concurrent and explicit
Tobias Pfeiffer
 
Elixir & Phoenix – fast, concurrent and explicit
Tobias Pfeiffer
 
Functional programming with clojure
Lucy Fang
 
Beyond PITS, Functional Principles for Software Architecture
Jayaram Sankaranarayanan
 
Dont Drive on the Railroad Tracks
Eugene Wallingford
 
Functional Objects in Ruby: new horizons – Valentine Ostakh
Ruby Meditation
 
Micropatterns
cameronp
 
Pune Clojure Course Outline
Baishampayan Ghose
 
Functional programming in ruby
Koen Handekyn
 
Thinking Functionally - John Stevenson - Codemotion Rome 2017
Codemotion
 
Thinking Functionally with Clojure
John Stevenson
 
Clojure: Practical functional approach on JVM
sunng87
 
Elixir & Phoenix - fast, concurrent and explicit
Tobias Pfeiffer
 
Funtional Ruby - Mikhail Bortnyk
Ruby Meditation
 
Functional Ruby
Amoniac OÜ
 
Esoteric LINQ and Structural Madness
Chris Eargle
 
Taking Inspiration From The Functional World
Piotr Solnica
 
Clojure 7-Languages
Pierre de Lacaze
 
(map Clojure everyday-tasks)
Jacek Laskowski
 
Ad

Recently uploaded (20)

PDF
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
PPTX
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
PPTX
Coefficient of Variance in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PPTX
Help for Correlations in IBM SPSS Statistics.pptx
Version 1 Analytics
 
PDF
The 5 Reasons for IT Maintenance - Arna Softech
Arna Softech
 
PPTX
Agentic Automation Journey Session 1/5: Context Grounding and Autopilot for E...
klpathrudu
 
PPTX
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
PDF
TheFutureIsDynamic-BoxLang witch Luis Majano.pdf
Ortus Solutions, Corp
 
PDF
MiniTool Power Data Recovery 8.8 With Crack New Latest 2025
bashirkhan333g
 
PDF
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
PPTX
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
PPTX
Milwaukee Marketo User Group - Summer Road Trip: Mapping and Personalizing Yo...
bbedford2
 
PDF
Top Agile Project Management Tools for Teams in 2025
Orangescrum
 
PDF
vMix Pro 28.0.0.42 Download vMix Registration key Bundle
kulindacore
 
PDF
Generic or Specific? Making sensible software design decisions
Bert Jan Schrijver
 
PDF
How to Hire AI Developers_ Step-by-Step Guide in 2025.pdf
DianApps Technologies
 
PPTX
Change Common Properties in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
Technical-Careers-Roadmap-in-Software-Market.pdf
Hussein Ali
 
PPTX
Hardware(Central Processing Unit ) CU and ALU
RizwanaKalsoom2
 
AI + DevOps = Smart Automation with devseccops.ai.pdf
Devseccops.ai
 
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
Coefficient of Variance in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
Help for Correlations in IBM SPSS Statistics.pptx
Version 1 Analytics
 
The 5 Reasons for IT Maintenance - Arna Softech
Arna Softech
 
Agentic Automation Journey Session 1/5: Context Grounding and Autopilot for E...
klpathrudu
 
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
TheFutureIsDynamic-BoxLang witch Luis Majano.pdf
Ortus Solutions, Corp
 
MiniTool Power Data Recovery 8.8 With Crack New Latest 2025
bashirkhan333g
 
Empower Your Tech Vision- Why Businesses Prefer to Hire Remote Developers fro...
logixshapers59
 
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
Milwaukee Marketo User Group - Summer Road Trip: Mapping and Personalizing Yo...
bbedford2
 
Top Agile Project Management Tools for Teams in 2025
Orangescrum
 
vMix Pro 28.0.0.42 Download vMix Registration key Bundle
kulindacore
 
Generic or Specific? Making sensible software design decisions
Bert Jan Schrijver
 
How to Hire AI Developers_ Step-by-Step Guide in 2025.pdf
DianApps Technologies
 
Change Common Properties in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Technical-Careers-Roadmap-in-Software-Market.pdf
Hussein Ali
 
Hardware(Central Processing Unit ) CU and ALU
RizwanaKalsoom2
 

Very basic functional design patterns