SlideShare a Scribd company logo
Algebraic Thinking for
Evolution of Pure
Functional Domain Models
Debasish Ghosh
@debasishg
Traveling back in time ..
more than 40 years ..
Copyright: https://www.npr.org/2014/06/17/318605598/turn-the-clock-back-or-forward-with-time-traveling-tales
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
c !:= 0
for i !:= 1 step 1 until n do
c !:= c + a[i] x b[i]
Von Neumann program for Inner Product
“It is dynamic and repetitive.
One must mentally execute it to understand it”
- John Backus
Def Innerproduct =
(Insert +) o (ApplyToAll X) o Transpose
Composition (o), Insert, ApplyToAll etc. are
functional forms that combine existing functions to
form new ones
Functional program for Inner Product
“It’s structure is helpful in understanding it
without mentally executing it”
- John Backus
- John Backus
“.. programs can be expressed in a language that has
an associated algebra. This algebra can be used to
transform programs and to solve some equations
whose " unknowns" are programs, in much the same
way one solves equations in high school algebra.
Algebraic transformations and proofs use the
language of the programs themselves, rather than the
language of logic, which talks about programs.”
What is an Algebra ?
Algebra is the study of algebraic structures
In mathematics, and more specifically in abstract
algebra, an algebraic structure is
a set (called carrier set or underlying set)
with one or more finitary operations defined on it
that satisfies a list of axioms
-Wikipedia
(https://en.wikipedia.org/wiki/Algebraic_structure)
SetA
ϕ : A × A → A
for (a, b) ∈ A
ϕ(a, b)
a ϕ b
given
a binary operation
for specific a, b
or
The Algebra of Sets
Algebraic Thinking
• Denotational Semantics
✦ programs and the objects they manipulate are symbolic
realizations of abstract mathematical objects
✦ the purpose of a mathematical semantics is to give a
correct and meaningful correspondence between programs
and mathematical entities in a way that is entirely
independent of an implementation [Scott & Strachey,
1971]
Algebraic Thinking
Denotational Semantics
Operational Thinking
• Operational Semantics
✦ formalize program implementation and how the various
functions must be computed or represented
✦ not much of a relevance towards algebraic reasoning
Option.apply[A](a: A): Option[A]
Option.empty[A]: Option[A]
Option[A]
A: Carrier Type of the algebra
Introduction Forms
Option.apply[A](a: A): Option[A]
Option.empty[A]: Option[A]
def f[A, B](func: A !=> B) = ???
optionA.map(f)
!// Option[B]
def f[A, B](func: A !=> Option[B]) = ???
optionA.!flatMap(f)
!// Option[B]
Option[A]
A: Carrier Type of the algebra
Introduction Forms
Combinators
Option.apply[A](a: A): Option[A]
Option.empty[A]: Option[A]
def f[A, B](func: A !=> B) = ???
optionA.map(f)
!// Option[B]
def f[A, B](func: A !=> Option[B]) = ???
optionA.!flatMap(f)
!// Option[B]
optionA.getOrElse(default)
!// A or B !>: A
Option[A]
A: Carrier Type of the algebra
Introduction Forms
Combinators
Eliminator Forms
Option.apply[A](a: A): Option[A]
Option.empty[A]: Option[A]
def f[A, B](func: A !=> B) = ???
optionA.map(f)
!// Option[B]
def f[A, B](func: A !=> Option[B]) = ???
optionA.!flatMap(f)
!// Option[B]
optionA.getOrElse(default)
!// A or B !>: A
Option.empty[Int].!flatMap(!!...) !== Option.empty[Int]
!// res1: Boolean = true
Option.empty[Int].map(!!...) !== Option.empty[Int]
!// res2: Boolean = true
Option[A]
A: Carrier Type of the algebra
Introduction Forms
Combinators
Eliminator Forms
Laws
A: Carrier Type of the algebra
Introduction Forms
Combinators
Eliminator Forms
Laws
algebra
• Thinking in terms of combinators (map/
!flatMap/fold) and their laws is algebraic
thinking
• Thinking in terms of concrete implementations
(pattern match with Some/None) is
operational thinking
Module with an algebra
trait Monoid[A] {
def zero: A
def combine(l: A, r: !=> A): A
}
!//identity
combine(x, zero) =
combine(zero, x) = x
!// associativity
combine(x, combine(y, z)) =
combine(combine(x, y), z)
Module with an Algebra
trait Foldable[F[_]] {
def foldl[A, B](as: F[A], z: B, f: (B, A) !=> B): B
def foldMap[A, B](as: F[A], f: A !=> B)
(implicit m: Monoid[B]): B =
foldl(as,
m.zero,
(b: B, a: A) !=> m.combine(b, f(a))
)
}
def mapReduce[F[_], A, B](as: F[A], f: A !=> B)
(implicit ff: Foldable[F], m: Monoid[B]) =
ff.foldMap(as, f)
https://stackoverflow.com/a/4765918
def mapReduce[F[_], A, B](as: F[A], f: A !=> B)
(implicit ff: Foldable[F], m: Monoid[B]) =
ff.foldMap(as, f)
https://stackoverflow.com/a/4765918
a complete map/reduce program abstracted as a
functional form
def mapReduce[F[_], A, B](as: F[A], f: A !=> B)
(implicit ff: Foldable[F], m: Monoid[B]) =
ff.foldMap(as, f)
https://stackoverflow.com/a/4765918
a complete map/reduce program abstracted as a
functional form
derived intuitively from the algebras of a fold and a
monoid
Building and understanding higher order abstractions is
much more intuitive using algebraic than operational
thinking
Building and understanding higher order abstractions is
much more intuitive using algebraic than operational
thinking
algebraic thinking scales
Healthy recipes for an
algebra
(in a statically typed functional programming language)
Polymorphic
trait Monoid[A] {
def zero: A
def combine(l: A, r: !=> A): A
}
Lawful
!//identity
combine(x, zero) =
combine(zero, x) = x
!// associativity
combine(x, combine(y, z)) =
combine(combine(x, y), z)
Compositional
trait Foldable[F[_]] {
def foldl[A, B](as: F[A], z: B,
f: (B, A) !=> B): B
def foldMap[A, B](as: F[A], f: A !=> B)
(implicit m: Monoid[B]): B =
foldl(as, m.zero,
(b: B, a: A) !=> m.combine(b, f(a)))
}
Restricted
def mapReduce[F[_], A, B](as: F[A],
f: A !=> B)
(implicit ff: Foldable[F],
m: Monoid[B]) =
ff.foldMap(as, f)
f:A!=>B and g:B!=>C, we should
be able to reason that we can
compose f and g algebraically
to build a larger function h:A!=>C
Implementation
Independent
Open
trait Repository[M[_]] {
def query[A](key: String): M[Option[A]]
!//!..
}
What is a domain model ?
A domain model in problem solving and software engineering is a
conceptual model of all the topics related to a specific problem. It
describes the various entities, their attributes, roles, and
relationships, plus the constraints that govern the problem domain.
It does not describe the solutions to the problem.
Wikipedia (http://en.wikipedia.org/wiki/Domain_model)
https://msdn.microsoft.com/en-us/library/jj591560.aspx
A Bounded Context
• has a consistent vocabulary
• a set of domain behaviors modeled as
functions on domain objects
implemented as types
• each of the behaviors honor a set of
business rules
• related behaviors grouped as modules
Domain Model = ∪(i) Bounded Context(i)
Bounded Context = { m[T1,T2,..] | T(i) ∈ Types }
Module = { f(x,y,..) | p(x,y) ∈ Domain Rules }
• domain function
• on an object of types x, y, ..
• composes with other functions
• closed under composition
• business rules
Domain Model = ∪(i) Bounded Context(i)
Bounded Context = { m[T1,T2,..] | T(i) ∈ Types }
Module = { f(x,y,..) | p(x,y) ∈ Domain Rules }
• domain function
• on an object of types x, y, ..
• composes with other functions
• closed under composition
• business rules
Domain Algebra
Domain Algebra
Client places order
- flexible format
1
Client places order
- flexible format
Transform to internal domain
model entity and place for execution
1 2
Client places order
- flexible format
Transform to internal domain
model entity and place for execution
Trade & Allocate to
client accounts
1 2
3
def orders(csvOrder: String): M[List[Order]]
def execute(orders: List[Order],
market: Market,
brokerAccountNo: AccountNo)
: M[List[Execution]]
def allocate(executions: List[Execution],
clientAccounts: List[AccountNo])
: M[List[Trade]]
trait Trading[M[_]] {
}
Effect Type that parameterizes
the Trading algebra
def orders(csvOrder: String): M[NonEmptyList[Order]]
def execute(orders: NonEmptyList[Order],
market: Market,
brokerAccountNo: AccountNo)
: M[NonEmptyList[Execution]]
def allocate(executions: NonEmptyList[Execution],
clientAccounts: NonEmptyList[AccountNo])
: M[NonEmptyList[Trade]]
trait Trading[M[_]] {
}
Effect Type that parameterizes
the Trading algebra
Effects
• an algebraic way of handling computational
effects like non-determinism, probabilistic non-
determinism, exceptions, interactive input-
output, side-effects, continuations etc.
• first formalized by Plotkin and Power [2003]
Option[A]
Either[A,B]
(partiality)
(disjunction)
List[A]
(non-determinism)
Reader[E,A]
(read from environment aka dependency Injection)
Writer[W,A]
(logging)
State[S,A]
(state management)
IO[A]
(external side-effects)
.. and there are many many more ..
F[A]
The answer that the
effect computes
The additional stuff
modeling the computation
• Error handling ?
• throw / catch exceptions is not RT
• Partiality ?
• partial functions can report runtime exceptions if
invoked with unhandled arguments (violates RT)
• Reading configuration information from environment ?
• may result in code repetition if not properly handled
• Logging ?
Side-effects
Side-effects
• Database writes
• Writing to a message queue
• Reading from stdin / files
• Interacting with any external resource
• Changing state in place
modularity
side-effects don’t compose
def orders(csvOrder: String): M[NonEmptyList[Order]]
def execute(orders: NonEmptyList[Order],
market: Market,
brokerAccountNo: AccountNo)
: M[NonEmptyList[Execution]]
def allocate(executions: NonEmptyList[Execution],
clientAccounts: NonEmptyList[AccountNo])
: M[NonEmptyList[Trade]]
trait Trading[M[_]] {
}
Effect Types offer compositionality even in the
presence of side-effects
All M[_]’s indicate that some
computation is going on here
• The M[_] that we saw is an opaque type - it
has no denotation till we give it one
• The denotation that we give to M[_] depends
on the semantics of compositionality that we
would like to have for our domain model
behaviors
The Program
def generateTrade[M[_]: Monad](T: Trading[M]) = for {
orders !<- T.orders(csvOrders)
executions !<- T.execute(orders, Market.NewYork, brokerAccountNo)
trades !<- T.allocate(executions, clientAccountNos)
} yield trades
The Program
def generateTrade[M[_]: Monad](T: Trading[M]) = for {
orders !<- T.orders(csvOrders)
executions !<- T.execute(orders, Market.NewYork, brokerAccountNo)
trades !<- T.allocate(executions, clientAccountNos)
} yield trades
Composition of the algebra of a Monad with our domain algebra of trading
Parametricity
• Trading module is polymorphic on M[_].We could
have committed to Trading[IO] upfront - but then
we are making decisions on behalf of the call site.This is
premature evaluation
• In implementation we can say M[_]: Monad and
suddenly the only operations available to us are pure
and !flatMap.This reduces the surface area of
implementation.With IO we could have done anything
in the implementation.
def postBalance(trades: NonEmptyList[Trade]
: F[NonEmptyList[Balance]]
trait Accounting[M[_]] {
}
Effect Type that parameterizes
the Accounting algebra
The Program
def generateTradeAndPostBalance[M[_]:Monad]
(T:Trading[M], A:Accounting[M]) = for {
orders !<- T.orders(csvOrders)
executions !<- T.execute(orders, Market.NewYork, brokerAccountNo)
trades !<- T.allocate(executions, clientAccountNos)
balances !<- A.postBalance(trades)
} yield (trades, balances)
The Program
def generateTradeAndPostBalance[M[_]:Monad]
(T:Trading[M], A:Accounting[M]) = for {
orders !<- T.orders(csvOrders)
executions !<- T.execute(orders, Market.NewYork, brokerAccountNo)
trades !<- T.allocate(executions, clientAccountNos)
balances !<- A.postBalance(trades)
} yield (trades, balances)
Composition of multiple domain algebras
• .. we have intentionally kept the algebra open
for interpretation ..
• .. there are use cases where you would like to
have multiple interpreters for the same
algebra ..
Interpreters
class TradingInterpreter[M[+_]]
(implicit E: MonadError[M, Throwable],
R: ApplicativeAsk[M, Repository[M]])
extends Trading[M] {
!//!..
}
monad with error handling
asks for a repository
from the environment
Interpreters
class TradingInterpreter[M[+_]]
(implicit E: MonadError[M, Throwable],
R: ApplicativeAsk[M, Repository[M]])
extends Trading[M] {
!//!..
}
monad with error handling
asks for a repository
from the environment
InMemoryRepository[M]
DoobieRepository[M]
Finally ..
implicit val !.. = !//!..
generateTradeAndPostBalances(
new TradingInterpreter[IO],
new AccountingInterpreter[IO]
)
Effects
Side-effects
- Rob Norris at scale.bythebay.io talk - 2017 (https://www.youtube.com/
watch?v=po3wmq4S15A)
“Effects and side-effects are not the same thing. Effects are
good, side-effects are bugs.Their lexical similarity is really
unfortunate because people often conflate the two ideas”
Takeaways
• Algebra scales from that of one single data type to
an entire bounded context
• Algebras compose enabling composition of
domain behaviors
• Algebras let you focus on the compositionality
without any context of implementation
• Statically typed functional programming is
programming with algebras
Takeaways
• Abstract early, interpret as late as possible
• Abstractions / functions compose only when they are
abstract and parametric
• Modularity in the presence of side-effects is a challenge
• Effects as algebras are pure values that can compose based
on laws
• Honor the law of using the least powerful abstraction
that works
Algebraic Thinking for Evolution of Pure Functional Domain Models
Questions?
References
• Scott, D., and Strachey, C. [1971 ]. Towards a mathematical semantics for computer languages.
Proc. Symp. on Computers and Automata, Polytechnic Institute of Brooklyn; also Tech. Mon. PRG-6, Oxford U. Computing Lab., pp.
19-46.
• Gordon Plotkin, and John Power. “Algebraic Operations and Generic Effects.” Applied Categorical Structures 11 (1): 69–94. 2003.
doi:10.1023/A:1023064908962.

More Related Content

PDF
Functional Patterns in Domain Modeling
PDF
Tagless Final Encoding - Algebras and Interpreters and also Programs
PDF
Fusing Transformations of Strict Scala Collections with Views
PDF
Domain Modeling in a Functional World
PDF
Functional Domain Modeling - The ZIO 2 Way
PDF
Power of functions in a typed world
PDF
Compositionality and Category Theory - a montage of slides/transcript for sec...
PPTX
Capabilities for Resources and Effects
Functional Patterns in Domain Modeling
Tagless Final Encoding - Algebras and Interpreters and also Programs
Fusing Transformations of Strict Scala Collections with Views
Domain Modeling in a Functional World
Functional Domain Modeling - The ZIO 2 Way
Power of functions in a typed world
Compositionality and Category Theory - a montage of slides/transcript for sec...
Capabilities for Resources and Effects

What's hot (20)

PDF
Monoids - Part 1 - with examples using Scalaz and Cats
PDF
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
PDF
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
PDF
Point free or die - tacit programming in Haskell and beyond
PDF
Refactoring Functional Type Classes
PPTX
Kotlin functions
PDF
Sequence and Traverse - Part 1
PDF
Code Refactoring Cheatsheet
PPTX
Compilers Are Databases
PDF
The Functional Programming Triad of Map, Filter and Fold
PDF
Left and Right Folds - Comparison of a mathematical definition and a programm...
PPTX
ORC File & Vectorization - Improving Hive Data Storage and Query Performance
PDF
Hash DoS Attack
PPTX
Jasper Reports.pptx
PDF
ZIO Queue
PDF
Haskell study 12
ODP
jBPM6 Updates
PDF
non-strict functions, bottom and scala by-name parameters
PDF
SHACL Overview
PDF
NDC12_Lockless게임서버설계와구현
Monoids - Part 1 - with examples using Scalaz and Cats
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Point free or die - tacit programming in Haskell and beyond
Refactoring Functional Type Classes
Kotlin functions
Sequence and Traverse - Part 1
Code Refactoring Cheatsheet
Compilers Are Databases
The Functional Programming Triad of Map, Filter and Fold
Left and Right Folds - Comparison of a mathematical definition and a programm...
ORC File & Vectorization - Improving Hive Data Storage and Query Performance
Hash DoS Attack
Jasper Reports.pptx
ZIO Queue
Haskell study 12
jBPM6 Updates
non-strict functions, bottom and scala by-name parameters
SHACL Overview
NDC12_Lockless게임서버설계와구현
Ad

Similar to Algebraic Thinking for Evolution of Pure Functional Domain Models (20)

PDF
Architectural Patterns in Building Modular Domain Models
PDF
An Algebraic Approach to Functional Domain Modeling
PDF
Mining Functional Patterns
PDF
Functional Scala
PPTX
Functional IO and Effects
PDF
Functional and Algebraic Domain Modeling
PDF
Why functional programming and category theory strongly matters - Piotr Parad...
PDF
Why functional programming and category theory strongly matters
PDF
Functional Programming Patterns for the Pragmatic Programmer
PPTX
Programming in python
PDF
Oh, All the things you'll traverse
PDF
Mcs 011 solved assignment 2015-16
PDF
Functions, Types, Programs and Effects
PDF
Functors
PPTX
BEN520 FUNDAMENTALS OF BOENGINEERING II-4 week-lecture 4.pptx
PDF
Actors and functional_reactive_programming
PDF
Monads and Monoids by Oleksiy Dyagilev
PDF
Big picture of category theory in scala with deep dive into contravariant and...
PDF
Big picture of category theory in scala with deep dive into contravariant and...
PPTX
data structure notes for engi DSA1 (2).pptx
Architectural Patterns in Building Modular Domain Models
An Algebraic Approach to Functional Domain Modeling
Mining Functional Patterns
Functional Scala
Functional IO and Effects
Functional and Algebraic Domain Modeling
Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters
Functional Programming Patterns for the Pragmatic Programmer
Programming in python
Oh, All the things you'll traverse
Mcs 011 solved assignment 2015-16
Functions, Types, Programs and Effects
Functors
BEN520 FUNDAMENTALS OF BOENGINEERING II-4 week-lecture 4.pptx
Actors and functional_reactive_programming
Monads and Monoids by Oleksiy Dyagilev
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
data structure notes for engi DSA1 (2).pptx
Ad

More from Debasish Ghosh (10)

PDF
Effects, Algebraically Yours using Scala
PDF
Approximation Data Structures for Streaming Applications
PDF
Functional and Algebraic Domain Modeling
PDF
From functional to Reactive - patterns in domain modeling
PDF
Domain Modeling with Functions - an algebraic approach
PDF
Property based Testing - generative data & executable domain rules
PDF
Big Data - architectural concerns for the new age
PDF
Functional and Event Driven - another approach to domain modeling
PPT
DSL - expressive syntax on top of a clean semantic model
PPT
Dependency Injection in Scala - Beyond the Cake Pattern
Effects, Algebraically Yours using Scala
Approximation Data Structures for Streaming Applications
Functional and Algebraic Domain Modeling
From functional to Reactive - patterns in domain modeling
Domain Modeling with Functions - an algebraic approach
Property based Testing - generative data & executable domain rules
Big Data - architectural concerns for the new age
Functional and Event Driven - another approach to domain modeling
DSL - expressive syntax on top of a clean semantic model
Dependency Injection in Scala - Beyond the Cake Pattern

Recently uploaded (20)

PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
Spectroscopy.pptx food analysis technology
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PPT
Teaching material agriculture food technology
PDF
KodekX | Application Modernization Development
PPTX
Big Data Technologies - Introduction.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Network Security Unit 5.pdf for BCA BBA.
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Review of recent advances in non-invasive hemoglobin estimation
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Advanced methodologies resolving dimensionality complications for autism neur...
Unlocking AI with Model Context Protocol (MCP)
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Programs and apps: productivity, graphics, security and other tools
Spectroscopy.pptx food analysis technology
The AUB Centre for AI in Media Proposal.docx
Per capita expenditure prediction using model stacking based on satellite ima...
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Teaching material agriculture food technology
KodekX | Application Modernization Development
Big Data Technologies - Introduction.pptx

Algebraic Thinking for Evolution of Pure Functional Domain Models

  • 1. Algebraic Thinking for Evolution of Pure Functional Domain Models Debasish Ghosh @debasishg
  • 2. Traveling back in time .. more than 40 years .. Copyright: https://www.npr.org/2014/06/17/318605598/turn-the-clock-back-or-forward-with-time-traveling-tales
  • 5. c !:= 0 for i !:= 1 step 1 until n do c !:= c + a[i] x b[i] Von Neumann program for Inner Product “It is dynamic and repetitive. One must mentally execute it to understand it” - John Backus
  • 6. Def Innerproduct = (Insert +) o (ApplyToAll X) o Transpose Composition (o), Insert, ApplyToAll etc. are functional forms that combine existing functions to form new ones Functional program for Inner Product “It’s structure is helpful in understanding it without mentally executing it” - John Backus
  • 7. - John Backus “.. programs can be expressed in a language that has an associated algebra. This algebra can be used to transform programs and to solve some equations whose " unknowns" are programs, in much the same way one solves equations in high school algebra. Algebraic transformations and proofs use the language of the programs themselves, rather than the language of logic, which talks about programs.”
  • 8. What is an Algebra ? Algebra is the study of algebraic structures In mathematics, and more specifically in abstract algebra, an algebraic structure is a set (called carrier set or underlying set) with one or more finitary operations defined on it that satisfies a list of axioms -Wikipedia (https://en.wikipedia.org/wiki/Algebraic_structure)
  • 9. SetA ϕ : A × A → A for (a, b) ∈ A ϕ(a, b) a ϕ b given a binary operation for specific a, b or The Algebra of Sets
  • 10. Algebraic Thinking • Denotational Semantics ✦ programs and the objects they manipulate are symbolic realizations of abstract mathematical objects ✦ the purpose of a mathematical semantics is to give a correct and meaningful correspondence between programs and mathematical entities in a way that is entirely independent of an implementation [Scott & Strachey, 1971]
  • 12. Operational Thinking • Operational Semantics ✦ formalize program implementation and how the various functions must be computed or represented ✦ not much of a relevance towards algebraic reasoning
  • 13. Option.apply[A](a: A): Option[A] Option.empty[A]: Option[A] Option[A] A: Carrier Type of the algebra Introduction Forms
  • 14. Option.apply[A](a: A): Option[A] Option.empty[A]: Option[A] def f[A, B](func: A !=> B) = ??? optionA.map(f) !// Option[B] def f[A, B](func: A !=> Option[B]) = ??? optionA.!flatMap(f) !// Option[B] Option[A] A: Carrier Type of the algebra Introduction Forms Combinators
  • 15. Option.apply[A](a: A): Option[A] Option.empty[A]: Option[A] def f[A, B](func: A !=> B) = ??? optionA.map(f) !// Option[B] def f[A, B](func: A !=> Option[B]) = ??? optionA.!flatMap(f) !// Option[B] optionA.getOrElse(default) !// A or B !>: A Option[A] A: Carrier Type of the algebra Introduction Forms Combinators Eliminator Forms
  • 16. Option.apply[A](a: A): Option[A] Option.empty[A]: Option[A] def f[A, B](func: A !=> B) = ??? optionA.map(f) !// Option[B] def f[A, B](func: A !=> Option[B]) = ??? optionA.!flatMap(f) !// Option[B] optionA.getOrElse(default) !// A or B !>: A Option.empty[Int].!flatMap(!!...) !== Option.empty[Int] !// res1: Boolean = true Option.empty[Int].map(!!...) !== Option.empty[Int] !// res2: Boolean = true Option[A] A: Carrier Type of the algebra Introduction Forms Combinators Eliminator Forms Laws
  • 17. A: Carrier Type of the algebra Introduction Forms Combinators Eliminator Forms Laws algebra
  • 18. • Thinking in terms of combinators (map/ !flatMap/fold) and their laws is algebraic thinking • Thinking in terms of concrete implementations (pattern match with Some/None) is operational thinking
  • 19. Module with an algebra trait Monoid[A] { def zero: A def combine(l: A, r: !=> A): A } !//identity combine(x, zero) = combine(zero, x) = x !// associativity combine(x, combine(y, z)) = combine(combine(x, y), z)
  • 20. Module with an Algebra trait Foldable[F[_]] { def foldl[A, B](as: F[A], z: B, f: (B, A) !=> B): B def foldMap[A, B](as: F[A], f: A !=> B) (implicit m: Monoid[B]): B = foldl(as, m.zero, (b: B, a: A) !=> m.combine(b, f(a)) ) }
  • 21. def mapReduce[F[_], A, B](as: F[A], f: A !=> B) (implicit ff: Foldable[F], m: Monoid[B]) = ff.foldMap(as, f) https://stackoverflow.com/a/4765918
  • 22. def mapReduce[F[_], A, B](as: F[A], f: A !=> B) (implicit ff: Foldable[F], m: Monoid[B]) = ff.foldMap(as, f) https://stackoverflow.com/a/4765918 a complete map/reduce program abstracted as a functional form
  • 23. def mapReduce[F[_], A, B](as: F[A], f: A !=> B) (implicit ff: Foldable[F], m: Monoid[B]) = ff.foldMap(as, f) https://stackoverflow.com/a/4765918 a complete map/reduce program abstracted as a functional form derived intuitively from the algebras of a fold and a monoid
  • 24. Building and understanding higher order abstractions is much more intuitive using algebraic than operational thinking
  • 25. Building and understanding higher order abstractions is much more intuitive using algebraic than operational thinking algebraic thinking scales
  • 26. Healthy recipes for an algebra (in a statically typed functional programming language)
  • 27. Polymorphic trait Monoid[A] { def zero: A def combine(l: A, r: !=> A): A }
  • 28. Lawful !//identity combine(x, zero) = combine(zero, x) = x !// associativity combine(x, combine(y, z)) = combine(combine(x, y), z)
  • 29. Compositional trait Foldable[F[_]] { def foldl[A, B](as: F[A], z: B, f: (B, A) !=> B): B def foldMap[A, B](as: F[A], f: A !=> B) (implicit m: Monoid[B]): B = foldl(as, m.zero, (b: B, a: A) !=> m.combine(b, f(a))) }
  • 30. Restricted def mapReduce[F[_], A, B](as: F[A], f: A !=> B) (implicit ff: Foldable[F], m: Monoid[B]) = ff.foldMap(as, f)
  • 31. f:A!=>B and g:B!=>C, we should be able to reason that we can compose f and g algebraically to build a larger function h:A!=>C Implementation Independent
  • 32. Open trait Repository[M[_]] { def query[A](key: String): M[Option[A]] !//!.. }
  • 33. What is a domain model ? A domain model in problem solving and software engineering is a conceptual model of all the topics related to a specific problem. It describes the various entities, their attributes, roles, and relationships, plus the constraints that govern the problem domain. It does not describe the solutions to the problem. Wikipedia (http://en.wikipedia.org/wiki/Domain_model)
  • 35. A Bounded Context • has a consistent vocabulary • a set of domain behaviors modeled as functions on domain objects implemented as types • each of the behaviors honor a set of business rules • related behaviors grouped as modules
  • 36. Domain Model = ∪(i) Bounded Context(i) Bounded Context = { m[T1,T2,..] | T(i) ∈ Types } Module = { f(x,y,..) | p(x,y) ∈ Domain Rules } • domain function • on an object of types x, y, .. • composes with other functions • closed under composition • business rules
  • 37. Domain Model = ∪(i) Bounded Context(i) Bounded Context = { m[T1,T2,..] | T(i) ∈ Types } Module = { f(x,y,..) | p(x,y) ∈ Domain Rules } • domain function • on an object of types x, y, .. • composes with other functions • closed under composition • business rules Domain Algebra Domain Algebra
  • 38. Client places order - flexible format 1
  • 39. Client places order - flexible format Transform to internal domain model entity and place for execution 1 2
  • 40. Client places order - flexible format Transform to internal domain model entity and place for execution Trade & Allocate to client accounts 1 2 3
  • 41. def orders(csvOrder: String): M[List[Order]] def execute(orders: List[Order], market: Market, brokerAccountNo: AccountNo) : M[List[Execution]] def allocate(executions: List[Execution], clientAccounts: List[AccountNo]) : M[List[Trade]] trait Trading[M[_]] { } Effect Type that parameterizes the Trading algebra
  • 42. def orders(csvOrder: String): M[NonEmptyList[Order]] def execute(orders: NonEmptyList[Order], market: Market, brokerAccountNo: AccountNo) : M[NonEmptyList[Execution]] def allocate(executions: NonEmptyList[Execution], clientAccounts: NonEmptyList[AccountNo]) : M[NonEmptyList[Trade]] trait Trading[M[_]] { } Effect Type that parameterizes the Trading algebra
  • 43. Effects • an algebraic way of handling computational effects like non-determinism, probabilistic non- determinism, exceptions, interactive input- output, side-effects, continuations etc. • first formalized by Plotkin and Power [2003]
  • 44. Option[A] Either[A,B] (partiality) (disjunction) List[A] (non-determinism) Reader[E,A] (read from environment aka dependency Injection) Writer[W,A] (logging) State[S,A] (state management) IO[A] (external side-effects) .. and there are many many more ..
  • 45. F[A] The answer that the effect computes The additional stuff modeling the computation
  • 46. • Error handling ? • throw / catch exceptions is not RT • Partiality ? • partial functions can report runtime exceptions if invoked with unhandled arguments (violates RT) • Reading configuration information from environment ? • may result in code repetition if not properly handled • Logging ? Side-effects
  • 47. Side-effects • Database writes • Writing to a message queue • Reading from stdin / files • Interacting with any external resource • Changing state in place
  • 49. def orders(csvOrder: String): M[NonEmptyList[Order]] def execute(orders: NonEmptyList[Order], market: Market, brokerAccountNo: AccountNo) : M[NonEmptyList[Execution]] def allocate(executions: NonEmptyList[Execution], clientAccounts: NonEmptyList[AccountNo]) : M[NonEmptyList[Trade]] trait Trading[M[_]] { } Effect Types offer compositionality even in the presence of side-effects All M[_]’s indicate that some computation is going on here
  • 50. • The M[_] that we saw is an opaque type - it has no denotation till we give it one • The denotation that we give to M[_] depends on the semantics of compositionality that we would like to have for our domain model behaviors
  • 51. The Program def generateTrade[M[_]: Monad](T: Trading[M]) = for { orders !<- T.orders(csvOrders) executions !<- T.execute(orders, Market.NewYork, brokerAccountNo) trades !<- T.allocate(executions, clientAccountNos) } yield trades
  • 52. The Program def generateTrade[M[_]: Monad](T: Trading[M]) = for { orders !<- T.orders(csvOrders) executions !<- T.execute(orders, Market.NewYork, brokerAccountNo) trades !<- T.allocate(executions, clientAccountNos) } yield trades Composition of the algebra of a Monad with our domain algebra of trading
  • 53. Parametricity • Trading module is polymorphic on M[_].We could have committed to Trading[IO] upfront - but then we are making decisions on behalf of the call site.This is premature evaluation • In implementation we can say M[_]: Monad and suddenly the only operations available to us are pure and !flatMap.This reduces the surface area of implementation.With IO we could have done anything in the implementation.
  • 54. def postBalance(trades: NonEmptyList[Trade] : F[NonEmptyList[Balance]] trait Accounting[M[_]] { } Effect Type that parameterizes the Accounting algebra
  • 55. The Program def generateTradeAndPostBalance[M[_]:Monad] (T:Trading[M], A:Accounting[M]) = for { orders !<- T.orders(csvOrders) executions !<- T.execute(orders, Market.NewYork, brokerAccountNo) trades !<- T.allocate(executions, clientAccountNos) balances !<- A.postBalance(trades) } yield (trades, balances)
  • 56. The Program def generateTradeAndPostBalance[M[_]:Monad] (T:Trading[M], A:Accounting[M]) = for { orders !<- T.orders(csvOrders) executions !<- T.execute(orders, Market.NewYork, brokerAccountNo) trades !<- T.allocate(executions, clientAccountNos) balances !<- A.postBalance(trades) } yield (trades, balances) Composition of multiple domain algebras
  • 57. • .. we have intentionally kept the algebra open for interpretation .. • .. there are use cases where you would like to have multiple interpreters for the same algebra ..
  • 58. Interpreters class TradingInterpreter[M[+_]] (implicit E: MonadError[M, Throwable], R: ApplicativeAsk[M, Repository[M]]) extends Trading[M] { !//!.. } monad with error handling asks for a repository from the environment
  • 59. Interpreters class TradingInterpreter[M[+_]] (implicit E: MonadError[M, Throwable], R: ApplicativeAsk[M, Repository[M]]) extends Trading[M] { !//!.. } monad with error handling asks for a repository from the environment InMemoryRepository[M] DoobieRepository[M]
  • 60. Finally .. implicit val !.. = !//!.. generateTradeAndPostBalances( new TradingInterpreter[IO], new AccountingInterpreter[IO] )
  • 62. - Rob Norris at scale.bythebay.io talk - 2017 (https://www.youtube.com/ watch?v=po3wmq4S15A) “Effects and side-effects are not the same thing. Effects are good, side-effects are bugs.Their lexical similarity is really unfortunate because people often conflate the two ideas”
  • 63. Takeaways • Algebra scales from that of one single data type to an entire bounded context • Algebras compose enabling composition of domain behaviors • Algebras let you focus on the compositionality without any context of implementation • Statically typed functional programming is programming with algebras
  • 64. Takeaways • Abstract early, interpret as late as possible • Abstractions / functions compose only when they are abstract and parametric • Modularity in the presence of side-effects is a challenge • Effects as algebras are pure values that can compose based on laws • Honor the law of using the least powerful abstraction that works
  • 67. References • Scott, D., and Strachey, C. [1971 ]. Towards a mathematical semantics for computer languages. Proc. Symp. on Computers and Automata, Polytechnic Institute of Brooklyn; also Tech. Mon. PRG-6, Oxford U. Computing Lab., pp. 19-46. • Gordon Plotkin, and John Power. “Algebraic Operations and Generic Effects.” Applied Categorical Structures 11 (1): 69–94. 2003. doi:10.1023/A:1023064908962.