SlideShare une entreprise Scribd logo
1  sur  67
Télécharger pour lire hors ligne
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
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
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.

Contenu connexe

Tendances

Tendances (20)

From Scala Monadic Effects to Unison Algebraic Effects
From Scala Monadic Effects to Unison Algebraic EffectsFrom Scala Monadic Effects to Unison Algebraic Effects
From Scala Monadic Effects to Unison Algebraic Effects
 
Fusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with ViewsFusing Transformations of Strict Scala Collections with Views
Fusing Transformations of Strict Scala Collections with Views
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...Algebraic Data Types forData Oriented Programming - From Haskell and Scala t...
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
Refactoring: A First Example - Martin Fowler’s First Example of Refactoring, ...
 
Gentle Introduction to Scala
Gentle Introduction to ScalaGentle Introduction to Scala
Gentle Introduction to Scala
 
Kleisli Composition
Kleisli CompositionKleisli Composition
Kleisli Composition
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
The Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and FoldThe Functional Programming Triad of Map, Filter and Fold
The Functional Programming Triad of Map, Filter and Fold
 
Applicative style programming
Applicative style programmingApplicative style programming
Applicative style programming
 
Applicative Functor
Applicative FunctorApplicative Functor
Applicative Functor
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
 
The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...The aggregate function - from sequential and parallel folds to parallel aggre...
The aggregate function - from sequential and parallel folds to parallel aggre...
 
Ad hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and CatsAd hoc Polymorphism using Type Classes and Cats
Ad hoc Polymorphism using Type Classes and Cats
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
non-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parametersnon-strict functions, bottom and scala by-name parameters
non-strict functions, bottom and scala by-name parameters
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
 

Similaire à Algebraic Thinking for Evolution of Pure Functional Domain Models

Programming in python
Programming in pythonProgramming in python
Programming in python
Ivan Rojas
 

Similaire à Algebraic Thinking for Evolution of Pure Functional Domain Models (20)

Architectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain ModelsArchitectural Patterns in Building Modular Domain Models
Architectural Patterns in Building Modular Domain Models
 
An Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain ModelingAn Algebraic Approach to Functional Domain Modeling
An Algebraic Approach to Functional Domain Modeling
 
Mining Functional Patterns
Mining Functional PatternsMining Functional Patterns
Mining Functional Patterns
 
Functional Scala
Functional ScalaFunctional Scala
Functional Scala
 
Functional IO and Effects
Functional IO and EffectsFunctional IO and Effects
Functional IO and Effects
 
Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters - Piotr Parad...Why functional programming and category theory strongly matters - Piotr Parad...
Why functional programming and category theory strongly matters - Piotr Parad...
 
Why functional programming and category theory strongly matters
Why functional programming and category theory strongly mattersWhy functional programming and category theory strongly matters
Why functional programming and category theory strongly matters
 
Functional Programming Patterns for the Pragmatic Programmer
Functional Programming Patterns for the Pragmatic ProgrammerFunctional Programming Patterns for the Pragmatic Programmer
Functional Programming Patterns for the Pragmatic Programmer
 
Programming in python
Programming in pythonProgramming in python
Programming in python
 
Oh, All the things you'll traverse
Oh, All the things you'll traverseOh, All the things you'll traverse
Oh, All the things you'll traverse
 
Mcs 011 solved assignment 2015-16
Mcs 011 solved assignment 2015-16Mcs 011 solved assignment 2015-16
Mcs 011 solved assignment 2015-16
 
Functions, Types, Programs and Effects
Functions, Types, Programs and EffectsFunctions, Types, Programs and Effects
Functions, Types, Programs and Effects
 
Functors
FunctorsFunctors
Functors
 
Actors and functional_reactive_programming
Actors and functional_reactive_programmingActors and functional_reactive_programming
Actors and functional_reactive_programming
 
Monads and Monoids by Oleksiy Dyagilev
Monads and Monoids by Oleksiy DyagilevMonads and Monoids by Oleksiy Dyagilev
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...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...
 
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...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...
 
C-PPT.pdf
C-PPT.pdfC-PPT.pdf
C-PPT.pdf
 
Functional Programming in the Wild
Functional Programming in the WildFunctional Programming in the Wild
Functional Programming in the Wild
 
Functional programming with FSharp
Functional programming with FSharpFunctional programming with FSharp
Functional programming with FSharp
 

Plus de Debasish Ghosh

Plus de Debasish Ghosh (9)

Approximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming ApplicationsApproximation Data Structures for Streaming Applications
Approximation Data Structures for Streaming Applications
 
Functional and Algebraic Domain Modeling
Functional and Algebraic Domain ModelingFunctional and Algebraic Domain Modeling
Functional and Algebraic Domain Modeling
 
From functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modelingFrom functional to Reactive - patterns in domain modeling
From functional to Reactive - patterns in domain modeling
 
Domain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approachDomain Modeling with Functions - an algebraic approach
Domain Modeling with Functions - an algebraic approach
 
Property based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rulesProperty based Testing - generative data & executable domain rules
Property based Testing - generative data & executable domain rules
 
Big Data - architectural concerns for the new age
Big Data - architectural concerns for the new ageBig Data - architectural concerns for the new age
Big Data - architectural concerns for the new age
 
Functional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modelingFunctional and Event Driven - another approach to domain modeling
Functional and Event Driven - another approach to domain modeling
 
DSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic modelDSL - expressive syntax on top of a clean semantic model
DSL - expressive syntax on top of a clean semantic model
 
Dependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake PatternDependency Injection in Scala - Beyond the Cake Pattern
Dependency Injection in Scala - Beyond the Cake Pattern
 

Dernier

Dernier (20)

Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 

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
  • 3.
  • 4.
  • 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
  • 65.
  • 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.