SlideShare a Scribd company logo
Advanced Tagless Final -
Saying farewell to Free
Luka Jacobowitz • flatMap(Oslo)
Software Developer at
codecentric
Co-organizer of ScalaDus
and IdrisDus
Maintainer of cats,
cats-effect, cats-mtl,
OutWatch
Enthusiastic about FP
About me
Overview
● Motivation (Free vs
Tagless Final)
● Program optimization
● Interpreter
transformations
● Stack-safety
● Conclusions
Motivation
● Tagless Final is cool
● Certain problems are still very hard to solve
while staying within the constraints of the
interpreter pattern
● Learn about new libraries to help with these
problems
● Have fun along the way!
Free vs. Tagless
Free vs. Tagless (For interpreter pattern)
Advantage Free
● Free Applicative allows us
to inspect the inner
structure of programs and
optimize
● Stack safe by default
Advantage Tagless Final
● Almost no boilerplate
● Much more performant
● Not married to the
Monad/Applicative
constraint
Program optimization
“Optimization in general requires peek ahead which
requires data structures”
With Free we have a data structure, how could it
possibly work for Tagless Final?
Program optimization
Solution:
Interpret it twice!
With a little help from sphynx!
Program optimization - example
trait KVStore[F[_]] {
def get(key: String): F[Option[String]]
def put(key: String, a: String): F[Unit]
}
def program[F[_]: Applicative](gets: List[String])
(puts: List[(String, String)])
(F: KVStore[F]): F[List[String]] =
puts.traverse(t => F.put(t._1, t._2))
*> gets.traverse(F.get).map(_.flatten)
Program optimization - example
What are some potential optimizations for this
program?
● Run actions in parallel
● Remove duplicates
● Put and then Get with same key should not perform
a Get action
First step: Extracting information from our program
We pre-interpret our program to get the information
we need to optimize
● To do so, we need an Applicative F[_]
● We can “lift” any Monoid into an Applicative
using Const.
● Our pre-interpreter should be of type
KVStore[Const[M, ?]]
Extraction
case class KVStoreInfo(gets: Set[String], puts: Map[String, String])
val extractor = new KVStore[Const[KVStoreInfo, ?]] {
def get(key: String): Const[KVStoreInfo, Option[String]] =
Const(KVStoreInfo(Set(key), Map.empty))
def put(key: String, v: String): Const[KVStoreInfo, Unit] =
Const(KVStoreInfo(Set.empty, Map(key -> v)))
}
val extracted: KVStoreInfo = program(gs, ps)(extractor).getConst
Next step: Defining a new interpreter using our new info
Now that we have the information we desire, we can
use it to define an optimized interpreter
● We could precompute values and store them
● That way our interpreter only has to look up the
values
● Since this will be effectful, it will be of type
IO[KVStore[IO]] meaning an IO that will compute a
new IO-interpreter for KVStore
Optimizing
val optimizedInterp = info.gets.filterNot(info.puts.contains)
.parTraverse(key => interp.get(key).map(_.map(s => (key, s))))
.map { list: List[Option[(String, String)]] =>
val table: Map[String, String] = list.flatten.toMap
new KVStore[IO] {
def get(key: String): IO[Option[String]] =
table.get(key).orElse(info.puts.get(key)) match {
case Some(a) => Option(a).pure[IO]
case None => interp.get(key)
}
def put(key: String, v: String): IO[Unit] = interp.put(key, v)
}
}
Let’s put it all together
val interp: KVStore[IO] = ???
val gets = List("Dog", "Bird", "Mouse", "Bird")
val puts = List("Cat" -> "Cat!", "Dog" -> "Dog!")
val info: KVStoreInfo = program(gets, puts)(extractor).getConst
val result: IO[List[String]] = program(gets, puts)(optimizedInterp)
val naiveResult: IO[List[String]] = program(gets, puts)(interp)
Result: initial naive interpreter
naiveResult.unsafeRunSync()
// Hit Network for: Put Cat -> Cat!
// Hit Network for: Put Dog -> Dog!
// Hit Network for: Get Dog
// Hit Network for: Get Bird
// Hit Network for: Get Mouse
// Hit Network for: Get Bird
Result: optimized interpreter
result.unsafeRunSync()
// Hit Network for: Get Bird
// Hit Network for: Get Mouse
// Hit Network for: Put Cat -> Cat!
// Hit Network for: Put Dog -> Dog!
Can we do better?
More precisely, can we generalize this?
Yes!
The Sphynx Optimizer
trait Optimizer[Alg[_[_]], F[_]: Monad] {
type M: Monoid
def extract: Alg[Const[M, ?]]
def rebuild(m: M, interpreter: Alg[F]): F[Alg[F]]
def optimize[A](p: Alg[F] => F[A]): Alg[F] => F[A] =
{ (interpreter: Alg[F]) =>
val m: M = p(extract).getConst
rebuild(m, interpreter).flatMap(interp => p(interp))
}
}
Lifting into a larger context
import sphynx.Optimizer
import sphynx.syntax._
def monadicProgram[F[_]: Monad](F: KVStore[F])
(implicit O: Optimizer[KVStore, F]): F[Unit] = for {
cat <- F.get("Cat")
list <- program(cat.toList, List.empty).optimize(F)
_ <- F.put("Birds", list.headOption.getOrElse("Finch"))
} yield ()
More cool sphynx features
● StaticOptimizer
● SemigroupalOptimizer
Interpreter transformations
Interpreter transformation
Given an algebra of the form Alg[_[_]] and appropriate
interpreter will have the form Alg[F] where F is the type
we’re interpreting into.
How can we turn an Alg[F] into an Alg[G]?
FunctorK!
Mainecoon - FunctorK
trait FunctorK[A[_[_]] {
def mapK[F[_], G[_]](a: A[F])(n: F ~> G): A[G]
}
@autoFunctorK
trait KVStore[F[_]] {
def get(key: String): F[Option[String]]
def put(key: String, a: String): F[Unit]
}
Mainecoon - FunctorK
val toTask: IO ~> Task = λ[IO ~> Task](_.to[Task])
val taskInterp: KVStore[Task] =
KVStore[IO].mapK(toTask)
Stack safety
Tagless final programs are only stack safe when their target
monad is stack safe.
Free Monads on the other hand guarantee this to be the case.
Solution?
Interpret program into Free
Made super easy with Mainecoon!
Mainecoon - Stack safety
def toFree[F[_]]: F ~> Free[F, ?] =
λ[F ~> Free[F, ?]](t => Free.liftF(t))
program(tryInterp.mapK(toFree))
.foldMap(FunctionK.id)
More cool Mainecoon features
● InvariantK, ContravariantK
● CartesianK (SemigroupalK)
Conclusions
Tagless final is great for separating problem description
from problem solution.
With these additional approaches we can keep this layer of
abstraction, while sacrificing none of the performance or
stack safety.
Scala as a language isn’t quite there yet to make full use
of some of these advanced techniques, but we can find
workarounds.
Thank you for
listening!
Twitter: @LukaJacobowitz
GitHub: LukaJCB

More Related Content

What's hot

Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
John De Goes
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
Oliver Daff
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
John De Goes
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
John De Goes
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
John De Goes
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
John De Goes
 
The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming Language
John De Goes
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
John De Goes
 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
Aleksandras Smirnovas
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
John De Goes
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
John De Goes
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
John De Goes
 
Why The Free Monad isn't Free
Why The Free Monad isn't FreeWhy The Free Monad isn't Free
Why The Free Monad isn't Free
Kelley Robinson
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
John De Goes
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
Jason Larsen
 
Hive function-cheat-sheet
Hive function-cheat-sheetHive function-cheat-sheet
Hive function-cheat-sheet
Dr. Volkan OBAN
 
Scalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaScalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with Scala
Daniel Sebban
 
GUL UC3M - Introduction to functional programming
GUL UC3M - Introduction to functional programmingGUL UC3M - Introduction to functional programming
GUL UC3M - Introduction to functional programming
David Muñoz Díaz
 
Functional Programming in Swift
Functional Programming in SwiftFunctional Programming in Swift
Functional Programming in Swift
Saugat Gautam
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Philip Schwarz
 

What's hot (20)

Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
MTL Versus Free
MTL Versus FreeMTL Versus Free
MTL Versus Free
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
The Next Great Functional Programming Language
The Next Great Functional Programming LanguageThe Next Great Functional Programming Language
The Next Great Functional Programming Language
 
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional ProgrammingZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
 
Map, Reduce and Filter in Swift
Map, Reduce and Filter in SwiftMap, Reduce and Filter in Swift
Map, Reduce and Filter in Swift
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
 
Refactoring Functional Type Classes
Refactoring Functional Type ClassesRefactoring Functional Type Classes
Refactoring Functional Type Classes
 
First-Class Patterns
First-Class PatternsFirst-Class Patterns
First-Class Patterns
 
Why The Free Monad isn't Free
Why The Free Monad isn't FreeWhy The Free Monad isn't Free
Why The Free Monad isn't Free
 
Scalaz 8: A Whole New Game
Scalaz 8: A Whole New GameScalaz 8: A Whole New Game
Scalaz 8: A Whole New Game
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
 
Hive function-cheat-sheet
Hive function-cheat-sheetHive function-cheat-sheet
Hive function-cheat-sheet
 
Scalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with ScalaScalapeno18 - Thinking Less with Scala
Scalapeno18 - Thinking Less with Scala
 
GUL UC3M - Introduction to functional programming
GUL UC3M - Introduction to functional programmingGUL UC3M - Introduction to functional programming
GUL UC3M - Introduction to functional programming
 
Functional Programming in Swift
Functional Programming in SwiftFunctional Programming in Swift
Functional Programming in Swift
 
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
Side by Side - Scala and Java Adaptations of Martin Fowler’s Javascript Refac...
 

Similar to Advanced Tagless Final - Saying Farewell to Free

Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)
Hermann Hueck
 
Advance Scala - Oleg Mürk
Advance Scala - Oleg MürkAdvance Scala - Oleg Mürk
Advance Scala - Oleg Mürk
Planet OS
 
Behm Shah Pagerank
Behm Shah PagerankBehm Shah Pagerank
Behm Shah Pagerankgothicane
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
Fabernovel
 
PyData NYC 2019
PyData NYC 2019PyData NYC 2019
PyData NYC 2019
Li Jin
 
Dafunctor
DafunctorDafunctor
Dafunctor
Buganini Chiu
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
Andrei Solntsev
 
Writing DSL with Applicative Functors
Writing DSL with Applicative FunctorsWriting DSL with Applicative Functors
Writing DSL with Applicative Functors
David Galichet
 
C++ unit-1-part-11
C++ unit-1-part-11C++ unit-1-part-11
C++ unit-1-part-11
Jadavsejal
 
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
Raúl Raja Martínez
 
Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen TatarynovWorkshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Fwdays
 
Monads in Swift
Monads in SwiftMonads in Swift
Monads in Swift
Vincent Pradeilles
 
Go Programming Language (Golang)
Go Programming Language (Golang)Go Programming Language (Golang)
Go Programming Language (Golang)
Ishin Vin
 
Practical cats
Practical catsPractical cats
Practical cats
Raymond Tay
 
Use PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language ParserUse PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language Parser
Yodalee
 
Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1
Robert Stern
 
Machine learning with py torch
Machine learning with py torchMachine learning with py torch
Machine learning with py torch
Riza Fahmi
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
scalaconfjp
 
Kpi driven-java-development
Kpi driven-java-developmentKpi driven-java-development
Kpi driven-java-development
Anirban Bhattacharjee
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scalaStratio
 

Similar to Advanced Tagless Final - Saying Farewell to Free (20)

Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)Composing an App with Free Monads (using Cats)
Composing an App with Free Monads (using Cats)
 
Advance Scala - Oleg Mürk
Advance Scala - Oleg MürkAdvance Scala - Oleg Mürk
Advance Scala - Oleg Mürk
 
Behm Shah Pagerank
Behm Shah PagerankBehm Shah Pagerank
Behm Shah Pagerank
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
PyData NYC 2019
PyData NYC 2019PyData NYC 2019
PyData NYC 2019
 
Dafunctor
DafunctorDafunctor
Dafunctor
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Writing DSL with Applicative Functors
Writing DSL with Applicative FunctorsWriting DSL with Applicative Functors
Writing DSL with Applicative Functors
 
C++ unit-1-part-11
C++ unit-1-part-11C++ unit-1-part-11
C++ unit-1-part-11
 
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
 
Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen TatarynovWorkshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
Workshop "Can my .NET application use less CPU / RAM?", Yevhen Tatarynov
 
Monads in Swift
Monads in SwiftMonads in Swift
Monads in Swift
 
Go Programming Language (Golang)
Go Programming Language (Golang)Go Programming Language (Golang)
Go Programming Language (Golang)
 
Practical cats
Practical catsPractical cats
Practical cats
 
Use PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language ParserUse PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language Parser
 
Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1Golang basics for Java developers - Part 1
Golang basics for Java developers - Part 1
 
Machine learning with py torch
Machine learning with py torchMachine learning with py torch
Machine learning with py torch
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Kpi driven-java-development
Kpi driven-java-developmentKpi driven-java-development
Kpi driven-java-development
 
Introduction to Asynchronous scala
Introduction to Asynchronous scalaIntroduction to Asynchronous scala
Introduction to Asynchronous scala
 

More from Luka Jacobowitz

Monoids, monoids, monoids
Monoids, monoids, monoidsMonoids, monoids, monoids
Monoids, monoids, monoids
Luka Jacobowitz
 
Up and Running with the Typelevel Stack
Up and Running with the Typelevel StackUp and Running with the Typelevel Stack
Up and Running with the Typelevel Stack
Luka Jacobowitz
 
Principled Error Handling - Scalapeño
Principled Error Handling - ScalapeñoPrincipled Error Handling - Scalapeño
Principled Error Handling - Scalapeño
Luka Jacobowitz
 
What Referential Transparency can do for you
What Referential Transparency can do for youWhat Referential Transparency can do for you
What Referential Transparency can do for you
Luka Jacobowitz
 
Scala UA 2017
Scala UA 2017Scala UA 2017
Scala UA 2017
Luka Jacobowitz
 
Reactive Programming in the Browser feat. Scala.js and Rx
Reactive Programming in the Browser feat. Scala.js and RxReactive Programming in the Browser feat. Scala.js and Rx
Reactive Programming in the Browser feat. Scala.js and Rx
Luka Jacobowitz
 
Reactive Programming in the Browser feat. Scala.js and PureScript
Reactive Programming in the Browser feat. Scala.js and PureScriptReactive Programming in the Browser feat. Scala.js and PureScript
Reactive Programming in the Browser feat. Scala.js and PureScript
Luka Jacobowitz
 

More from Luka Jacobowitz (7)

Monoids, monoids, monoids
Monoids, monoids, monoidsMonoids, monoids, monoids
Monoids, monoids, monoids
 
Up and Running with the Typelevel Stack
Up and Running with the Typelevel StackUp and Running with the Typelevel Stack
Up and Running with the Typelevel Stack
 
Principled Error Handling - Scalapeño
Principled Error Handling - ScalapeñoPrincipled Error Handling - Scalapeño
Principled Error Handling - Scalapeño
 
What Referential Transparency can do for you
What Referential Transparency can do for youWhat Referential Transparency can do for you
What Referential Transparency can do for you
 
Scala UA 2017
Scala UA 2017Scala UA 2017
Scala UA 2017
 
Reactive Programming in the Browser feat. Scala.js and Rx
Reactive Programming in the Browser feat. Scala.js and RxReactive Programming in the Browser feat. Scala.js and Rx
Reactive Programming in the Browser feat. Scala.js and Rx
 
Reactive Programming in the Browser feat. Scala.js and PureScript
Reactive Programming in the Browser feat. Scala.js and PureScriptReactive Programming in the Browser feat. Scala.js and PureScript
Reactive Programming in the Browser feat. Scala.js and PureScript
 

Recently uploaded

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
Globus
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
abdulrafaychaudhry
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
XfilesPro
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Yara Milbes
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 

Recently uploaded (20)

AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
How to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good PracticesHow to Position Your Globus Data Portal for Success Ten Good Practices
How to Position Your Globus Data Portal for Success Ten Good Practices
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, BetterWebinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
Webinar: Salesforce Document Management 2.0 - Smarter, Faster, Better
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 

Advanced Tagless Final - Saying Farewell to Free

  • 1. Advanced Tagless Final - Saying farewell to Free Luka Jacobowitz • flatMap(Oslo)
  • 2. Software Developer at codecentric Co-organizer of ScalaDus and IdrisDus Maintainer of cats, cats-effect, cats-mtl, OutWatch Enthusiastic about FP About me
  • 3. Overview ● Motivation (Free vs Tagless Final) ● Program optimization ● Interpreter transformations ● Stack-safety ● Conclusions
  • 4. Motivation ● Tagless Final is cool ● Certain problems are still very hard to solve while staying within the constraints of the interpreter pattern ● Learn about new libraries to help with these problems ● Have fun along the way!
  • 6. Free vs. Tagless (For interpreter pattern) Advantage Free ● Free Applicative allows us to inspect the inner structure of programs and optimize ● Stack safe by default Advantage Tagless Final ● Almost no boilerplate ● Much more performant ● Not married to the Monad/Applicative constraint
  • 7. Program optimization “Optimization in general requires peek ahead which requires data structures” With Free we have a data structure, how could it possibly work for Tagless Final?
  • 8. Program optimization Solution: Interpret it twice! With a little help from sphynx!
  • 9. Program optimization - example trait KVStore[F[_]] { def get(key: String): F[Option[String]] def put(key: String, a: String): F[Unit] } def program[F[_]: Applicative](gets: List[String]) (puts: List[(String, String)]) (F: KVStore[F]): F[List[String]] = puts.traverse(t => F.put(t._1, t._2)) *> gets.traverse(F.get).map(_.flatten)
  • 10. Program optimization - example What are some potential optimizations for this program? ● Run actions in parallel ● Remove duplicates ● Put and then Get with same key should not perform a Get action
  • 11. First step: Extracting information from our program We pre-interpret our program to get the information we need to optimize ● To do so, we need an Applicative F[_] ● We can “lift” any Monoid into an Applicative using Const. ● Our pre-interpreter should be of type KVStore[Const[M, ?]]
  • 12. Extraction case class KVStoreInfo(gets: Set[String], puts: Map[String, String]) val extractor = new KVStore[Const[KVStoreInfo, ?]] { def get(key: String): Const[KVStoreInfo, Option[String]] = Const(KVStoreInfo(Set(key), Map.empty)) def put(key: String, v: String): Const[KVStoreInfo, Unit] = Const(KVStoreInfo(Set.empty, Map(key -> v))) } val extracted: KVStoreInfo = program(gs, ps)(extractor).getConst
  • 13. Next step: Defining a new interpreter using our new info Now that we have the information we desire, we can use it to define an optimized interpreter ● We could precompute values and store them ● That way our interpreter only has to look up the values ● Since this will be effectful, it will be of type IO[KVStore[IO]] meaning an IO that will compute a new IO-interpreter for KVStore
  • 14. Optimizing val optimizedInterp = info.gets.filterNot(info.puts.contains) .parTraverse(key => interp.get(key).map(_.map(s => (key, s)))) .map { list: List[Option[(String, String)]] => val table: Map[String, String] = list.flatten.toMap new KVStore[IO] { def get(key: String): IO[Option[String]] = table.get(key).orElse(info.puts.get(key)) match { case Some(a) => Option(a).pure[IO] case None => interp.get(key) } def put(key: String, v: String): IO[Unit] = interp.put(key, v) } }
  • 15. Let’s put it all together val interp: KVStore[IO] = ??? val gets = List("Dog", "Bird", "Mouse", "Bird") val puts = List("Cat" -> "Cat!", "Dog" -> "Dog!") val info: KVStoreInfo = program(gets, puts)(extractor).getConst val result: IO[List[String]] = program(gets, puts)(optimizedInterp) val naiveResult: IO[List[String]] = program(gets, puts)(interp)
  • 16. Result: initial naive interpreter naiveResult.unsafeRunSync() // Hit Network for: Put Cat -> Cat! // Hit Network for: Put Dog -> Dog! // Hit Network for: Get Dog // Hit Network for: Get Bird // Hit Network for: Get Mouse // Hit Network for: Get Bird
  • 17. Result: optimized interpreter result.unsafeRunSync() // Hit Network for: Get Bird // Hit Network for: Get Mouse // Hit Network for: Put Cat -> Cat! // Hit Network for: Put Dog -> Dog!
  • 18. Can we do better? More precisely, can we generalize this? Yes!
  • 19. The Sphynx Optimizer trait Optimizer[Alg[_[_]], F[_]: Monad] { type M: Monoid def extract: Alg[Const[M, ?]] def rebuild(m: M, interpreter: Alg[F]): F[Alg[F]] def optimize[A](p: Alg[F] => F[A]): Alg[F] => F[A] = { (interpreter: Alg[F]) => val m: M = p(extract).getConst rebuild(m, interpreter).flatMap(interp => p(interp)) } }
  • 20. Lifting into a larger context import sphynx.Optimizer import sphynx.syntax._ def monadicProgram[F[_]: Monad](F: KVStore[F]) (implicit O: Optimizer[KVStore, F]): F[Unit] = for { cat <- F.get("Cat") list <- program(cat.toList, List.empty).optimize(F) _ <- F.put("Birds", list.headOption.getOrElse("Finch")) } yield ()
  • 21. More cool sphynx features ● StaticOptimizer ● SemigroupalOptimizer
  • 23. Interpreter transformation Given an algebra of the form Alg[_[_]] and appropriate interpreter will have the form Alg[F] where F is the type we’re interpreting into. How can we turn an Alg[F] into an Alg[G]? FunctorK!
  • 24. Mainecoon - FunctorK trait FunctorK[A[_[_]] { def mapK[F[_], G[_]](a: A[F])(n: F ~> G): A[G] } @autoFunctorK trait KVStore[F[_]] { def get(key: String): F[Option[String]] def put(key: String, a: String): F[Unit] }
  • 25. Mainecoon - FunctorK val toTask: IO ~> Task = λ[IO ~> Task](_.to[Task]) val taskInterp: KVStore[Task] = KVStore[IO].mapK(toTask)
  • 26. Stack safety Tagless final programs are only stack safe when their target monad is stack safe. Free Monads on the other hand guarantee this to be the case. Solution? Interpret program into Free Made super easy with Mainecoon!
  • 27. Mainecoon - Stack safety def toFree[F[_]]: F ~> Free[F, ?] = λ[F ~> Free[F, ?]](t => Free.liftF(t)) program(tryInterp.mapK(toFree)) .foldMap(FunctionK.id)
  • 28. More cool Mainecoon features ● InvariantK, ContravariantK ● CartesianK (SemigroupalK)
  • 29. Conclusions Tagless final is great for separating problem description from problem solution. With these additional approaches we can keep this layer of abstraction, while sacrificing none of the performance or stack safety. Scala as a language isn’t quite there yet to make full use of some of these advanced techniques, but we can find workarounds.
  • 30. Thank you for listening! Twitter: @LukaJacobowitz GitHub: LukaJCB