SlideShare a Scribd company logo
1 of 16
Download to read offline
Tagless Final Encoding
Algebras and Interpreters
and also Programs
an introduction, through the work of Gabriel Volpe
Algebras
Tagless Final
Encoding
@philip_schwarz
slides by http://fpilluminated.com/
This slide deck is a quick, introductory look, at Tagless Final, as explained (in rather more depth
than is possible or appropriate here) by Gabriel in his great book: Practical FP in Scala, a Hands-
on Approach.
In the first six slides, we are going to see Gabriel introduce the key elements of the technique.
Tagless final is all about algebras and interpreters. Yet,
something is missing when it comes to writing applicationsā€¦
Tagless final is a great technique used to
structure purely functional applications.
Yes, as youā€™ll see, to the two official pillars of Tagless Final, i.e. algebras and interpreters, Gabriel
adds a third one: programs.
Algebras
Tagless Final
Encoding
@philip_schwarz
Algebras
An algebra describes a new language (DSL) within a host language, in this case, Scala.
This is a tagless final encoded algebra; tagless algebra, or algebra for short: a simple interface that
abstracts over the effect type using a type constructor F[_].
Do not confuse algebras with typeclasses, which in Scala, happen to share the same encoding.
The difference is that typeclasses should have coherent instances, whereas tagless algebras could have
many implementations, or more commonly called interpreters.
ā€¦
Overall, tagless algebras seem a perfect fit for encoding business concepts. For example, an algebra
responsible for managing items could be encoded as follows.
Nothing new, right? This tagless final encoded algebra is merely an interface that abstracts over the effect
type. Notice that neither the algebra nor its functions have any typeclass constraint.
If you find yourself needing to add a typeclass constraint, such as Monad, to your algebra, what you probably
need is a program.
The reason being that typeclass constraints define capabilities, which belong in programs and interpreters.
Algebras should remain completely abstract.
trait Items[F[_]] {
def getAll: F[List[Item]]
def add(item: Item): F[Unit]
}
trait Counter[F[_]] {
def increment: F[Unit]
def get: F[Int]
}
Tagless algebras should not have typeclass constraints
Tips
Interpreters
We would normally have two interpreters per algebra: one for testing and one for doing real things. For
instance, we could have two different implementations of our Counter.
A default interpreter using Redis.
And a test interpreter using an in-memory data structure.
Interpreters help us encapsulate state and allow separation of concerns: the interface knows nothing about
the implementation details. Moreover, interpreters can be written either using a concrete datatype such as
IO or going polymorphic all the way, as we did in this case.
object Counter {
@newtype case class RedisKey(value: String)
def make[F[_]: Functor](
key: RedisKey,
cmd: RedisCommands[F, String, Int]
): Counter[F] =
new Counter[F] {
def increment: F[Unit] =
cmd.increment(key.value).void
def get: F[Int] =
cmd.get(key.value).map(_.getOrElse(0))
}
}
def testCounter[F[_]](
ref: Ref[F, Int]
): Counter[F] = new Counter[F] {
def increment: F[Unit] = ref.update(_ + 1)
def get: F[Int] = ref.get
}
We are currently working our way through slides containing excerpts from Chapter 2: Tagless Final Encoding.
The next slide is an exception in that it contains an excerpt from Chapter1: Best Practices, which has already
introduced (in a less formal way), the concept of an interpreter for the Counter trait (without yet referring to
the latter as an algebra).
In-memory counter
Letā€™s say we need an in-memory counter that needs to be accessed and modified by other components. Here
is what our interface could look like.
It has a higher-kinded type F[_], representing an abstract effect, which most of the time ends up being IO,
but it could really be any other concrete type that fits the shape.
Next, we need to define an interpreter in the companion object of our interface, in this case using a Ref. We
will talk more about it in the next section.
ā€¦
Moving on, itā€™s worth highlighting that other programs will interact with this counter solely via its interface. E.g.
// prints out 0,1,6 when executed
def program(c: Counter[IO]): IO[Unit] =
for {
_ <- c.get.flatMap(IO.println)
_ <- c.increment
_ <- c.get.flatMap(IO.println)
_ <- c.increment.replicateA(5).void
_ <- c.get.flatMap(IO.println)
} yield ()
In the next chapter, we will discuss whether it is best to pass the dependency implicitly or explicitly.
object Counter {
def make[F[_]: Functor: Ref.Make]: F[Counter[F]] =
Ref.of[F, Int](0).map { ref =>
new Counter[F] {
def increment: F[Unit] = ref.update(_ + 1)
def get: F[Int] = ref.get
}
}
}
trait Counter[F[_]] {
def increment: F[Unit]
def get: F[Int]
}
import cats.Functor
import cats.effect.kernel.Ref
import cats.syntax.functor._
Programs
Tagless final is all about algebras and interpreters. Yet, something is missing when it comes to writing applications: we
need to use these algebras to describe business logic, and this logic belongs in what I like to call programs.
Although it is not an official name ā€“ and it is not mentioned in the original tagless final paper ā€“ it is how we will be
referring to such interfaces in this book.
Say we need to increase a counter every time there is a new item added. We could encode it as follows.
Observe the characteristics of this program. It is pure business logic, and it holds no state at all, which in any case,
must be encapsulated in the interpreters. Notice the typeclass constraints as well; it is a good practice to have them
in programs instead of tagless algebras.
ā€¦
Moreover, we can discuss typeclass constraints. In this case, we only need Apply to use *> (alias for productR).
However, it would also work with Applicative or Monad. The rule of thumb is to limit ourselves to adopt the least
powerful typeclass that gets the job done.
It is worth mentioning that Apply itself doesnā€™t specify the semantics of composition solely with this constraint, *>
might combine its arguments sequentially or parallelly, depending on the underlying typeclass instance. To ensure
our composition is sequential, we could use FlatMap instead of Apply.
class ItemsCounter[F[_]: Apply](
counter: Counter[F],
items: Items[F]
){
def addItem(item: Item): F[Unit] =
items.add(item) *>
counter.increment
}
Programs can make use of algebras and other programs
Notes
When adding a typeclass constraint, remember about the principle of least power
Tips
Other kinds of programs might be directly encoded as functions.
Furthermore, we could have programs composed of other programs.
Whether we encode programs in one way or another, they should describe pure business logic and nothing else.
The question is: what is pure business logic? We could try and define a set of rules to abide by. It is allowed to:
ā€¢ Combine pure computations in terms of tagless algebras and programs.
ā€“ Only doing what our effect constraints allows us to do.
ā€¢ Perform logging (or console stuff) only via a tagless algebra.
ā€“ In Chapter 8, we will see how to ignore logging or console stuff in tests, which are most of the time irrelevant in
such context.
You can use this as a reference. However, the answer should come up as a collective agreement within your team.
def program[F[_]: Console: Monad]: F[Unit] =
for {
_ <- Console[F].println("Enter your name: ")
n <- Console[F].readLine
_ <- Console[F].println(s"Hello $n!")
} yield ()
class MasterMind[F[_]: Console: Monad](
itemsCounter: ItemsCounter[F],
counter: Counter[F]
){
def logic(item: Item): F[Unit] =
for {
_ <- itemsCounter.addItem(item)
c <- counter.get
_ <- Console[F].println(s"Number of items: $c")
} yield ()
}
def program(counter: Counter[IO]): IO[Unit] =
for {
_ <- display(counter)
_ <- counter.increment
_ <- display(counter)
_ <- repeat(5){ counter.increment }
_ <- display(counter)
} yield ()
def display(counter: Counter[IO]): IO[Unit] =
counter.get.flatMap(IO.println)
def repeat(n: Int)(action: IO[Unit]): IO[Unit] =
action.replicateA(n).void
def program(c: Counter[IO]): IO[Unit] =
for {
_ <- c.get.flatMap(IO.println)
_ <- c.increment
_ <- c.get.flatMap(IO.println)
_ <- c.increment.replicateA(5).void
_ <- c.get.flatMap(IO.println)
} yield ()
REFACTOR
Letā€™s refactor a little bit the first program that we came across.
On the next slide, we are going to take that program and wrap it in a tiny application that can be executed.
We are also going to use a little bit of UML, to show how the program uses an algebra (i.e. an interface) implemented by an interpreter.
To do this, we are going to slightly abuse UML, along the lines described by Martin Fowler in https://martinfowler.com/bliki/BallAndSocket.html.
Program
Algebra
Interface Algebra is used (required) by Program.
Interface Algebra is realized (implemented) by Interpreter.
Interpreter
Algebra
Program Interpreter
Algebra
Interface Algebra, which is realized (implemented)
by Interpreter, is used (required) by Program.
Algebra
ball
Algebra interface.
In a further twist, Iā€™ll also be putting Algebra inside the ball.
socket
mated socket and ball
valid UML notation
invalid
UML
notation
@philip_schwarz
import cats.effect.IO
import cats.effect.IOApp.Simple
object Application extends Simple {
// prints out 0, 1, 6 when executed
override def run: IO[Unit] =
Counter.make[IO].flatMap(program(_))
private def program(counter: Counter[IO]): IO[Unit] =
for {
_ <- display(counter)
_ <- counter.increment
_ <- display(counter)
_ <- repeat(5){ counter.increment }
_ <- display(counter)
} yield ()
private def display(counter: Counter[IO]): IO[Unit] =
counter.get.flatMap(IO.println)
private def repeat(n: Int)(action: IO[Unit]): IO[Unit] =
action.replicateA(n).void
}
trait Counter[F[_]] {
def increment: F[Unit]
def get: F[Int]
}
Algebra
Program
object Counter {
def make[F[_]: Functor: Ref.Make]: F[Counter[F]] =
Ref.of[F, Int](0).map { ref =>
new Counter[F] {
def increment: F[Unit] =
ref.update(_ + 1)
def get: F[Int] =
ref.get
}
}
}
Interpreter
Next, we take the mastermind program that we saw earlier, and
use it in a tiny application that tests it a bit.
Because we are going to need it in the next slide, here is a much
pared down version of the Item referenced by the program.
import io.estatico.newtype.macros.newtype
import java.util.UUID
object item {
@newtype case class ItemId(value: UUID)
@newtype case class ItemName(value: String)
@newtype case class ItemDescription(value: String)
case class Item(uuid: ItemId, name: ItemName, description: ItemDescription)
}
class ItemsCounter[F[_]: Apply](
counter: Counter[F],
items: Items[F]
){
def addItem(item: Item): F[Unit] =
items.add(item) *>
counter.increment
}
class MasterMind[F[_]: Console: Monad](
itemsCounter: ItemsCounter[F],
counter: Counter[F]
){
def logic(item: Item): F[Unit] =
for {
_ <- itemsCounter.addItem(item)
c <- counter.get
_ <- Console[F].println(s"Number of items: $c")
} yield ()
}
trait Counter[F[_]] {
def increment: F[Unit]
def get: F[Int]
}
trait Items[F[_]] {
def getAll: F[List[Item]]
def add(item: Item): F[Unit]
}
object TestCounter {
def make[F[_]: Functor: Ref.Make]: F[Counter[F]] =
Ref.of[F, Int[(0).map { ref =>
new Counter[F] {
def increment: F[Unit] =
ref.update(_ + 1)
def get: F[Int] =
ref.get
}
}
object TestItems {
def make[F[_]: Functor : Ref.Make]: F[Items[F]] =
Ref.of[F, Map[ItemId, Item]](Map.empty).map { ref =>
new Items[F] {
def getAll: F[List[Item]] =
ref.get.map(_.values.toList)
def add(item: Item): F[Unit] =
ref.update(_ + (item.uuid -> item))
}
}
}
import cats.effect.IO
import cats.effect.IOApp.Simple
import item.{Item, ItemDescription, ItemId, ItemName}
import java.util.UUID
object TestMasterMindProgram extends Simple {
val item = Item(
ItemId(UUID.fromString("0c69d914-6ff6-11ee-b962-0242ac120002")),
ItemName("Practical FP in Scala"),
ItemDescription("A great book")
)
override def run: IO[Unit] = {
for {
counter <- TestCounter.make[IO]
items <- TestItems.make[IO]
itemsCounter = new ItemsCounter[IO](counter, items)
masterMind = new MasterMind(itemsCounter, counter)
itemsBefore <- items.getAll
countBefore <- counter.get
_ = assert(itemsBefore.isEmpty)
_ = assert(countBefore == 0)
_ <- masterMind.logic(item)
itemsAfter <- items.getAll
countAfter <- counter.get
_ = assert(itemsAfter.sameElements(List(item)))
_ = assert(countAfter == 1)
} yield ()
}
}
Algebra
Interpreter
Program
Algebra
Interpreter
Program
Program
Of course this was just a quick introduction to the Tagless Final technique.
See the book for much more depth, and many other important aspects of using the technique.
The next slide contains just a taster.
Some might question the decision to invest in this technique for a business application, claiming it entails great complexity.
This is a fair concern but letā€™s ask ourselves, whatā€™s the alternative? Using IO directly in the entire application? By all means,
this could work, but at what cost? At the very least, we would be giving up on parametricityā€  and the principle of least power.
There is a huge mix of concerns. How can we possibly
reason about this function? How can we even test it? We
got ourselves into a very uncomfortable situation.
Now letā€™s compare it against the abstract equivalent of
it. Instead of performing side-effects, we have now
typeclass constraints and capabilities.
Teams making use of this technique will immediately understand that all we can do in the body of the constrained function is to compose
Counter, Log, and Time actions sequentially as well as to use any property made available by the Monad constraint. It is true, however, that
the Scala compiler does not enforce it so this is up to the discipline of the team.
Since Scala is a hybrid language, the only thing stopping us from running wild side-effects in this function is self-discipline and peer reviews.
However, good practices are required in any team for multiple purposes, so I would argue it is not necessarily a bad thing, as we can do the same
thing in programs encoded directly in IO.
ā€  https://en.wikipedia.org/wiki/Parametricity
Thatā€™s all. I hope you found it useful.

More Related Content

What's hot

Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Philip Schwarz
Ā 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
Ā 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
Ā 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
Ā 
Point free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPoint free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPhilip Schwarz
Ā 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Philip Schwarz
Ā 
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 FoldPhilip Schwarz
Ā 
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 PatternDebasish Ghosh
Ā 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
Ā 
RxJS - The Basics & The Future
RxJS - The Basics & The FutureRxJS - The Basics & The Future
RxJS - The Basics & The FutureTracy Lee
Ā 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3Martin Odersky
Ā 
The Uniform Access Principle
The Uniform Access PrincipleThe Uniform Access Principle
The Uniform Access PrinciplePhilip Schwarz
Ā 
Javascript this keyword
Javascript this keywordJavascript this keyword
Javascript this keywordPham Huy Tung
Ā 
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 ViewsPhilip Schwarz
Ā 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
Ā 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...Philip Schwarz
Ā 
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, ...Philip Schwarz
Ā 
Applicative Functor
Applicative FunctorApplicative Functor
Applicative FunctorPhilip Schwarz
Ā 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaVladimir Kostyukov
Ā 

What's hot (20)

Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Ā 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Ā 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
Ā 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
Ā 
Point free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyondPoint free or die - tacit programming in Haskell and beyond
Point free or die - tacit programming in Haskell and beyond
Ā 
Sequence and Traverse - Part 2
Sequence and Traverse - Part 2Sequence and Traverse - Part 2
Sequence and Traverse - Part 2
Ā 
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
Ā 
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
Ā 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
Ā 
RxJS - The Basics & The Future
RxJS - The Basics & The FutureRxJS - The Basics & The Future
RxJS - The Basics & The Future
Ā 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
Ā 
The Uniform Access Principle
The Uniform Access PrincipleThe Uniform Access Principle
The Uniform Access Principle
Ā 
Javascript this keyword
Javascript this keywordJavascript this keyword
Javascript this keyword
Ā 
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
Ā 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Ā 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit ā€“ Haskell and...
Ā 
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, ...
Ā 
Applicative Functor
Applicative FunctorApplicative Functor
Applicative Functor
Ā 
Applicative style programming
Applicative style programmingApplicative style programming
Applicative style programming
Ā 
Purely Functional Data Structures in Scala
Purely Functional Data Structures in ScalaPurely Functional Data Structures in Scala
Purely Functional Data Structures in Scala
Ā 

Similar to Tagless Final Encoding - Algebras and Interpreters and also Programs

Java modular extension for operator overloading
Java modular extension for operator overloadingJava modular extension for operator overloading
Java modular extension for operator overloadingijpla
Ā 
Functional Effects - Part 1
Functional Effects - Part 1Functional Effects - Part 1
Functional Effects - Part 1Philip Schwarz
Ā 
Presentation 2.pptx
Presentation 2.pptxPresentation 2.pptx
Presentation 2.pptxziyadaslanbey
Ā 
Algorithm and c language
Algorithm and c languageAlgorithm and c language
Algorithm and c languagekamalbeydoun
Ā 
Book management system
Book management systemBook management system
Book management systemSHARDA SHARAN
Ā 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An OverviewIndrajit Das
Ā 
Tutorial basic of c ++lesson 1 eng ver
Tutorial basic of c ++lesson 1 eng verTutorial basic of c ++lesson 1 eng ver
Tutorial basic of c ++lesson 1 eng verQrembiezs Intruder
Ā 
Java 8-revealed
Java 8-revealedJava 8-revealed
Java 8-revealedHamed Hatami
Ā 
Functions in c++
Functions in c++Functions in c++
Functions in c++Asaye Dilbo
Ā 
Presentation 2 (1).pdf
Presentation 2 (1).pdfPresentation 2 (1).pdf
Presentation 2 (1).pdfziyadaslanbey
Ā 
Modeling Aspects with AP&P Components
Modeling Aspects with AP&P ComponentsModeling Aspects with AP&P Components
Modeling Aspects with AP&P Componentsmukhtarhudaya
Ā 
Introduction to c programming
Introduction to c programmingIntroduction to c programming
Introduction to c programmingAMAN ANAND
Ā 
C programming languag for cse students
C programming languag for cse studentsC programming languag for cse students
C programming languag for cse studentsAbdur Rahim
Ā 
Mastering Python lesson 4_functions_parameters_arguments
Mastering Python lesson 4_functions_parameters_argumentsMastering Python lesson 4_functions_parameters_arguments
Mastering Python lesson 4_functions_parameters_argumentsRuth Marvin
Ā 

Similar to Tagless Final Encoding - Algebras and Interpreters and also Programs (20)

Java modular extension for operator overloading
Java modular extension for operator overloadingJava modular extension for operator overloading
Java modular extension for operator overloading
Ā 
Functional Effects - Part 1
Functional Effects - Part 1Functional Effects - Part 1
Functional Effects - Part 1
Ā 
Function
FunctionFunction
Function
Ā 
Chapter 1.ppt
Chapter 1.pptChapter 1.ppt
Chapter 1.ppt
Ā 
Presentation 2.pptx
Presentation 2.pptxPresentation 2.pptx
Presentation 2.pptx
Ā 
Algorithm and c language
Algorithm and c languageAlgorithm and c language
Algorithm and c language
Ā 
Book management system
Book management systemBook management system
Book management system
Ā 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An Overview
Ā 
Tutorial basic of c ++lesson 1 eng ver
Tutorial basic of c ++lesson 1 eng verTutorial basic of c ++lesson 1 eng ver
Tutorial basic of c ++lesson 1 eng ver
Ā 
Java 8-revealed
Java 8-revealedJava 8-revealed
Java 8-revealed
Ā 
Functions in c++
Functions in c++Functions in c++
Functions in c++
Ā 
Function
FunctionFunction
Function
Ā 
Presentation 2 (1).pdf
Presentation 2 (1).pdfPresentation 2 (1).pdf
Presentation 2 (1).pdf
Ā 
Bcsl 031 solve assignment
Bcsl 031 solve assignmentBcsl 031 solve assignment
Bcsl 031 solve assignment
Ā 
Modeling Aspects with AP&P Components
Modeling Aspects with AP&P ComponentsModeling Aspects with AP&P Components
Modeling Aspects with AP&P Components
Ā 
ACM init()- Day 4
ACM init()- Day 4ACM init()- Day 4
ACM init()- Day 4
Ā 
Introduction to c programming
Introduction to c programmingIntroduction to c programming
Introduction to c programming
Ā 
C functions
C functionsC functions
C functions
Ā 
C programming languag for cse students
C programming languag for cse studentsC programming languag for cse students
C programming languag for cse students
Ā 
Mastering Python lesson 4_functions_parameters_arguments
Mastering Python lesson 4_functions_parameters_argumentsMastering Python lesson 4_functions_parameters_arguments
Mastering Python lesson 4_functions_parameters_arguments
Ā 

More from Philip Schwarz

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
Ā 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesPhilip Schwarz
Ā 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesPhilip Schwarz
Ā 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesPhilip Schwarz
Ā 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three ApproachesPhilip Schwarz
Ā 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaPhilip Schwarz
Ā 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaPhilip Schwarz
Ā 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaPhilip Schwarz
Ā 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsPhilip Schwarz
Ā 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Philip Schwarz
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an examplePhilip Schwarz
Ā 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...Philip Schwarz
Ā 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...Philip Schwarz
Ā 
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...Philip Schwarz
Ā 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsPhilip Schwarz
Ā 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Philip Schwarz
Ā 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Philip Schwarz
Ā 
The Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsThe Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsPhilip Schwarz
Ā 
The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1Philip Schwarz
Ā 

More from Philip Schwarz (20)

Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
Ā 
Folding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a seriesFolding Cheat Sheet #3 - third in a series
Folding Cheat Sheet #3 - third in a series
Ā 
Folding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a seriesFolding Cheat Sheet #2 - second in a series
Folding Cheat Sheet #2 - second in a series
Ā 
Folding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a seriesFolding Cheat Sheet #1 - first in a series
Folding Cheat Sheet #1 - first in a series
Ā 
Scala Left Fold Parallelisation - Three Approaches
Scala Left Fold Parallelisation- Three ApproachesScala Left Fold Parallelisation- Three Approaches
Scala Left Fold Parallelisation - Three Approaches
Ā 
A sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in ScalaA sighting of traverse_ function in Practical FP in Scala
A sighting of traverse_ function in Practical FP in Scala
Ā 
A sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in ScalaA sighting of traverseFilter and foldMap in Practical FP in Scala
A sighting of traverseFilter and foldMap in Practical FP in Scala
Ā 
A sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in ScalaA sighting of sequence function in Practical FP in Scala
A sighting of sequence function in Practical FP in Scala
Ā 
N-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets CatsN-Queens Combinatorial Puzzle meets Cats
N-Queens Combinatorial Puzzle meets Cats
Ā 
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Kleisli composition, flatMap, join, map, unit - implementation and interrelat...
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Ā 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Ā 
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
The Sieve of Eratosthenes - Part II - Genuine versus Unfaithful Sieve - Haske...
Ā 
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...Sum and Product Types -The Fruit Salad & Fruit Snack Example - From F# to Ha...
Sum and Product Types - The Fruit Salad & Fruit Snack Example - From F# to Ha...
Ā 
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...
Ā 
Jordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axiomsJordan Peterson - The pursuit of meaning and related ethical axioms
Jordan Peterson - The pursuit of meaning and related ethical axioms
Ā 
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Defining filter using (a) recursion (b) folding (c) folding with S, B and I c...
Ā 
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Defining filter using (a) recursion (b) folding with S, B and I combinators (...
Ā 
The Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor correctionsThe Sieve of Eratosthenes - Part 1 - with minor corrections
The Sieve of Eratosthenes - Part 1 - with minor corrections
Ā 
The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1The Sieve of Eratosthenes - Part 1
The Sieve of Eratosthenes - Part 1
Ā 

Recently uploaded

Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)
Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)
Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)jennyeacort
Ā 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
Ā 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
Ā 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
Ā 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
Ā 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
Ā 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
Ā 
Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024
Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024
Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024StefanoLambiase
Ā 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
Ā 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
Ā 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
Ā 
Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...soniya singh
Ā 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
Ā 
č‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1制作
č‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1åˆ¶ä½œč‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1制作
č‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1制作qr0udbr0
Ā 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....kzayra69
Ā 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
Ā 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
Ā 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
Ā 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noidabntitsolutionsrishis
Ā 

Recently uploaded (20)

Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)
Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)
Call UsšŸ”>ą¼’+91-9711147426ā‡›Call In girls karol bagh (Delhi)
Ā 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
Ā 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
Ā 
Hot Sexy call girls in Patel NagaršŸ” 9953056974 šŸ” escort Service
Hot Sexy call girls in Patel NagaršŸ” 9953056974 šŸ” escort ServiceHot Sexy call girls in Patel NagaršŸ” 9953056974 šŸ” escort Service
Hot Sexy call girls in Patel NagaršŸ” 9953056974 šŸ” escort Service
Ā 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
Ā 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
Ā 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
Ā 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
Ā 
Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024
Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024
Dealing with Cultural Dispersion ā€” Stefano Lambiase ā€” ICSE-SEIS 2024
Ā 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
Ā 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
Ā 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Ā 
Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi āž”ļø 8264348440 šŸ’‹šŸ“ž Independent Escort S...
Ā 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
Ā 
č‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1制作
č‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1åˆ¶ä½œč‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1制作
č‹±å›½UN学位čƁ,åŒ—å®‰ę™®é”æ大学ęƕäøščƁ书1:1制作
Ā 
What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....What are the key points to focus on before starting to learn ETL Development....
What are the key points to focus on before starting to learn ETL Development....
Ā 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
Ā 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
Ā 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Ā 
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in NoidaBuds n Tech IT Solutions: Top-Notch Web Services in Noida
Buds n Tech IT Solutions: Top-Notch Web Services in Noida
Ā 

Tagless Final Encoding - Algebras and Interpreters and also Programs

  • 1. Tagless Final Encoding Algebras and Interpreters and also Programs an introduction, through the work of Gabriel Volpe Algebras Tagless Final Encoding @philip_schwarz slides by http://fpilluminated.com/
  • 2. This slide deck is a quick, introductory look, at Tagless Final, as explained (in rather more depth than is possible or appropriate here) by Gabriel in his great book: Practical FP in Scala, a Hands- on Approach. In the first six slides, we are going to see Gabriel introduce the key elements of the technique. Tagless final is all about algebras and interpreters. Yet, something is missing when it comes to writing applicationsā€¦ Tagless final is a great technique used to structure purely functional applications. Yes, as youā€™ll see, to the two official pillars of Tagless Final, i.e. algebras and interpreters, Gabriel adds a third one: programs. Algebras Tagless Final Encoding @philip_schwarz
  • 3. Algebras An algebra describes a new language (DSL) within a host language, in this case, Scala. This is a tagless final encoded algebra; tagless algebra, or algebra for short: a simple interface that abstracts over the effect type using a type constructor F[_]. Do not confuse algebras with typeclasses, which in Scala, happen to share the same encoding. The difference is that typeclasses should have coherent instances, whereas tagless algebras could have many implementations, or more commonly called interpreters. ā€¦ Overall, tagless algebras seem a perfect fit for encoding business concepts. For example, an algebra responsible for managing items could be encoded as follows. Nothing new, right? This tagless final encoded algebra is merely an interface that abstracts over the effect type. Notice that neither the algebra nor its functions have any typeclass constraint. If you find yourself needing to add a typeclass constraint, such as Monad, to your algebra, what you probably need is a program. The reason being that typeclass constraints define capabilities, which belong in programs and interpreters. Algebras should remain completely abstract. trait Items[F[_]] { def getAll: F[List[Item]] def add(item: Item): F[Unit] } trait Counter[F[_]] { def increment: F[Unit] def get: F[Int] } Tagless algebras should not have typeclass constraints Tips
  • 4. Interpreters We would normally have two interpreters per algebra: one for testing and one for doing real things. For instance, we could have two different implementations of our Counter. A default interpreter using Redis. And a test interpreter using an in-memory data structure. Interpreters help us encapsulate state and allow separation of concerns: the interface knows nothing about the implementation details. Moreover, interpreters can be written either using a concrete datatype such as IO or going polymorphic all the way, as we did in this case. object Counter { @newtype case class RedisKey(value: String) def make[F[_]: Functor]( key: RedisKey, cmd: RedisCommands[F, String, Int] ): Counter[F] = new Counter[F] { def increment: F[Unit] = cmd.increment(key.value).void def get: F[Int] = cmd.get(key.value).map(_.getOrElse(0)) } } def testCounter[F[_]]( ref: Ref[F, Int] ): Counter[F] = new Counter[F] { def increment: F[Unit] = ref.update(_ + 1) def get: F[Int] = ref.get }
  • 5. We are currently working our way through slides containing excerpts from Chapter 2: Tagless Final Encoding. The next slide is an exception in that it contains an excerpt from Chapter1: Best Practices, which has already introduced (in a less formal way), the concept of an interpreter for the Counter trait (without yet referring to the latter as an algebra).
  • 6. In-memory counter Letā€™s say we need an in-memory counter that needs to be accessed and modified by other components. Here is what our interface could look like. It has a higher-kinded type F[_], representing an abstract effect, which most of the time ends up being IO, but it could really be any other concrete type that fits the shape. Next, we need to define an interpreter in the companion object of our interface, in this case using a Ref. We will talk more about it in the next section. ā€¦ Moving on, itā€™s worth highlighting that other programs will interact with this counter solely via its interface. E.g. // prints out 0,1,6 when executed def program(c: Counter[IO]): IO[Unit] = for { _ <- c.get.flatMap(IO.println) _ <- c.increment _ <- c.get.flatMap(IO.println) _ <- c.increment.replicateA(5).void _ <- c.get.flatMap(IO.println) } yield () In the next chapter, we will discuss whether it is best to pass the dependency implicitly or explicitly. object Counter { def make[F[_]: Functor: Ref.Make]: F[Counter[F]] = Ref.of[F, Int](0).map { ref => new Counter[F] { def increment: F[Unit] = ref.update(_ + 1) def get: F[Int] = ref.get } } } trait Counter[F[_]] { def increment: F[Unit] def get: F[Int] } import cats.Functor import cats.effect.kernel.Ref import cats.syntax.functor._
  • 7. Programs Tagless final is all about algebras and interpreters. Yet, something is missing when it comes to writing applications: we need to use these algebras to describe business logic, and this logic belongs in what I like to call programs. Although it is not an official name ā€“ and it is not mentioned in the original tagless final paper ā€“ it is how we will be referring to such interfaces in this book. Say we need to increase a counter every time there is a new item added. We could encode it as follows. Observe the characteristics of this program. It is pure business logic, and it holds no state at all, which in any case, must be encapsulated in the interpreters. Notice the typeclass constraints as well; it is a good practice to have them in programs instead of tagless algebras. ā€¦ Moreover, we can discuss typeclass constraints. In this case, we only need Apply to use *> (alias for productR). However, it would also work with Applicative or Monad. The rule of thumb is to limit ourselves to adopt the least powerful typeclass that gets the job done. It is worth mentioning that Apply itself doesnā€™t specify the semantics of composition solely with this constraint, *> might combine its arguments sequentially or parallelly, depending on the underlying typeclass instance. To ensure our composition is sequential, we could use FlatMap instead of Apply. class ItemsCounter[F[_]: Apply]( counter: Counter[F], items: Items[F] ){ def addItem(item: Item): F[Unit] = items.add(item) *> counter.increment } Programs can make use of algebras and other programs Notes When adding a typeclass constraint, remember about the principle of least power Tips
  • 8. Other kinds of programs might be directly encoded as functions. Furthermore, we could have programs composed of other programs. Whether we encode programs in one way or another, they should describe pure business logic and nothing else. The question is: what is pure business logic? We could try and define a set of rules to abide by. It is allowed to: ā€¢ Combine pure computations in terms of tagless algebras and programs. ā€“ Only doing what our effect constraints allows us to do. ā€¢ Perform logging (or console stuff) only via a tagless algebra. ā€“ In Chapter 8, we will see how to ignore logging or console stuff in tests, which are most of the time irrelevant in such context. You can use this as a reference. However, the answer should come up as a collective agreement within your team. def program[F[_]: Console: Monad]: F[Unit] = for { _ <- Console[F].println("Enter your name: ") n <- Console[F].readLine _ <- Console[F].println(s"Hello $n!") } yield () class MasterMind[F[_]: Console: Monad]( itemsCounter: ItemsCounter[F], counter: Counter[F] ){ def logic(item: Item): F[Unit] = for { _ <- itemsCounter.addItem(item) c <- counter.get _ <- Console[F].println(s"Number of items: $c") } yield () }
  • 9. def program(counter: Counter[IO]): IO[Unit] = for { _ <- display(counter) _ <- counter.increment _ <- display(counter) _ <- repeat(5){ counter.increment } _ <- display(counter) } yield () def display(counter: Counter[IO]): IO[Unit] = counter.get.flatMap(IO.println) def repeat(n: Int)(action: IO[Unit]): IO[Unit] = action.replicateA(n).void def program(c: Counter[IO]): IO[Unit] = for { _ <- c.get.flatMap(IO.println) _ <- c.increment _ <- c.get.flatMap(IO.println) _ <- c.increment.replicateA(5).void _ <- c.get.flatMap(IO.println) } yield () REFACTOR Letā€™s refactor a little bit the first program that we came across.
  • 10. On the next slide, we are going to take that program and wrap it in a tiny application that can be executed. We are also going to use a little bit of UML, to show how the program uses an algebra (i.e. an interface) implemented by an interpreter. To do this, we are going to slightly abuse UML, along the lines described by Martin Fowler in https://martinfowler.com/bliki/BallAndSocket.html. Program Algebra Interface Algebra is used (required) by Program. Interface Algebra is realized (implemented) by Interpreter. Interpreter Algebra Program Interpreter Algebra Interface Algebra, which is realized (implemented) by Interpreter, is used (required) by Program. Algebra ball Algebra interface. In a further twist, Iā€™ll also be putting Algebra inside the ball. socket mated socket and ball valid UML notation invalid UML notation @philip_schwarz
  • 11. import cats.effect.IO import cats.effect.IOApp.Simple object Application extends Simple { // prints out 0, 1, 6 when executed override def run: IO[Unit] = Counter.make[IO].flatMap(program(_)) private def program(counter: Counter[IO]): IO[Unit] = for { _ <- display(counter) _ <- counter.increment _ <- display(counter) _ <- repeat(5){ counter.increment } _ <- display(counter) } yield () private def display(counter: Counter[IO]): IO[Unit] = counter.get.flatMap(IO.println) private def repeat(n: Int)(action: IO[Unit]): IO[Unit] = action.replicateA(n).void } trait Counter[F[_]] { def increment: F[Unit] def get: F[Int] } Algebra Program object Counter { def make[F[_]: Functor: Ref.Make]: F[Counter[F]] = Ref.of[F, Int](0).map { ref => new Counter[F] { def increment: F[Unit] = ref.update(_ + 1) def get: F[Int] = ref.get } } } Interpreter
  • 12. Next, we take the mastermind program that we saw earlier, and use it in a tiny application that tests it a bit. Because we are going to need it in the next slide, here is a much pared down version of the Item referenced by the program. import io.estatico.newtype.macros.newtype import java.util.UUID object item { @newtype case class ItemId(value: UUID) @newtype case class ItemName(value: String) @newtype case class ItemDescription(value: String) case class Item(uuid: ItemId, name: ItemName, description: ItemDescription) }
  • 13. class ItemsCounter[F[_]: Apply]( counter: Counter[F], items: Items[F] ){ def addItem(item: Item): F[Unit] = items.add(item) *> counter.increment } class MasterMind[F[_]: Console: Monad]( itemsCounter: ItemsCounter[F], counter: Counter[F] ){ def logic(item: Item): F[Unit] = for { _ <- itemsCounter.addItem(item) c <- counter.get _ <- Console[F].println(s"Number of items: $c") } yield () } trait Counter[F[_]] { def increment: F[Unit] def get: F[Int] } trait Items[F[_]] { def getAll: F[List[Item]] def add(item: Item): F[Unit] } object TestCounter { def make[F[_]: Functor: Ref.Make]: F[Counter[F]] = Ref.of[F, Int[(0).map { ref => new Counter[F] { def increment: F[Unit] = ref.update(_ + 1) def get: F[Int] = ref.get } } object TestItems { def make[F[_]: Functor : Ref.Make]: F[Items[F]] = Ref.of[F, Map[ItemId, Item]](Map.empty).map { ref => new Items[F] { def getAll: F[List[Item]] = ref.get.map(_.values.toList) def add(item: Item): F[Unit] = ref.update(_ + (item.uuid -> item)) } } } import cats.effect.IO import cats.effect.IOApp.Simple import item.{Item, ItemDescription, ItemId, ItemName} import java.util.UUID object TestMasterMindProgram extends Simple { val item = Item( ItemId(UUID.fromString("0c69d914-6ff6-11ee-b962-0242ac120002")), ItemName("Practical FP in Scala"), ItemDescription("A great book") ) override def run: IO[Unit] = { for { counter <- TestCounter.make[IO] items <- TestItems.make[IO] itemsCounter = new ItemsCounter[IO](counter, items) masterMind = new MasterMind(itemsCounter, counter) itemsBefore <- items.getAll countBefore <- counter.get _ = assert(itemsBefore.isEmpty) _ = assert(countBefore == 0) _ <- masterMind.logic(item) itemsAfter <- items.getAll countAfter <- counter.get _ = assert(itemsAfter.sameElements(List(item))) _ = assert(countAfter == 1) } yield () } } Algebra Interpreter Program Algebra Interpreter Program Program
  • 14. Of course this was just a quick introduction to the Tagless Final technique. See the book for much more depth, and many other important aspects of using the technique. The next slide contains just a taster.
  • 15. Some might question the decision to invest in this technique for a business application, claiming it entails great complexity. This is a fair concern but letā€™s ask ourselves, whatā€™s the alternative? Using IO directly in the entire application? By all means, this could work, but at what cost? At the very least, we would be giving up on parametricityā€  and the principle of least power. There is a huge mix of concerns. How can we possibly reason about this function? How can we even test it? We got ourselves into a very uncomfortable situation. Now letā€™s compare it against the abstract equivalent of it. Instead of performing side-effects, we have now typeclass constraints and capabilities. Teams making use of this technique will immediately understand that all we can do in the body of the constrained function is to compose Counter, Log, and Time actions sequentially as well as to use any property made available by the Monad constraint. It is true, however, that the Scala compiler does not enforce it so this is up to the discipline of the team. Since Scala is a hybrid language, the only thing stopping us from running wild side-effects in this function is self-discipline and peer reviews. However, good practices are required in any team for multiple purposes, so I would argue it is not necessarily a bad thing, as we can do the same thing in programs encoded directly in IO. ā€  https://en.wikipedia.org/wiki/Parametricity
  • 16. Thatā€™s all. I hope you found it useful.