SlideShare a Scribd company logo
Ruslan Shevchenko, Kyiv, Ukraine.
<ruslan@shevchenko.kiev.ua>
proofspace.id
Embedding Generic Monadic Transformer into Scala.
{Can we return concurrent programming into mainstream? }
https://github.com/rssh/dotty-cps-async
Asynchronous control flow - Scala industrial usage.


for{
r1 <- cacheService.get(id) match
case Some(v) => IO.success(v)
case None => talkToServer(id).map{v =>
cacheService.update(id,v)
v
}
r2 <- talkToServer(r1.data)
result <- if (r2.isOk) then {
writeToFile(resultData) >>=
IO.println("done") >>=
true
} else {
IO.println("abort") >>=
false
}
} yield result
Monadic DSL on top of some effect system or. Future
Asynchronous control flow - Scala industrial usage.


for{
r1 <- cacheService.get(id) match
case Some(v) => IO.success(v)
case None => talkToServer(id).map{v =>
cacheService.update(id,v)
v
}
R2 <- talkToServer(r1.data)
result <- if (r2.isOk) then {
writeToFile(r1.data) >>=
IO.println("done") >>=
true
} else {
IO.println("abort") >>=
false
}
} yield result
Monadic DSL on top of some effect system or. Future
async[IO] {
val r1 = cacheService.getOrUpdate(id,
await(talkToServer(id)))
val r2 = talkToServer(r1.data)
if (r2.isOk) then
writeToFile(r1.data)
IO.println("done")
true
else
IO.println("abort")
false
}
"Mainstream" Control-Flow
over some effect system or Future
API (simpli
fi
ed)
Well-known async/await interface.
+ - generic monad
- ability to use higher-order functions without runtime support for continuations.
- automatic colouring (awaits can-be omitted if can be restored from the context)
def async[F[_]](f: T):F[T]
def await[F[_]](f: F[T]):T
transparent inline
def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T]
API (simpli
fi
ed)
@compileTimeOnly("await should be inside async block")
def await[G[_],T,F[_]](f: G[T])(using CpsMonadConversion[G,F], CpsMonadContext[F]):
//in real signature here is temporary class, to allow currying of type parameters
def async[F[_]](f: T):F[T]
def await[F[_]](f: F[T]):T
transparent inline
def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T]
API (simpli
fi
ed)
@compileTimeOnly("await should be inside async block")
def await[G[_],T,F[_]](f: G[T])(using CpsMonadConversion[G,F], CpsMonadContext[F]): T
Macro, evaluated during typing
transparent inline
def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T]
API (simpli
fi
ed)
@compileTimeOnly("await should be inside async block")
def await[G[_],T,F[_]](f: G[T])(using CpsMonadCoversion[G,F], CpsMonadContext[F]): T
F[_]. — Our monad : Future[T], IO[T], … etc
G[_]. — Monad which we await
transparent inline
def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T]
API (simpli
fi
ed)
@compileTimeOnly("await should be inside async block")
def await[G[_],T,F[_]](f: G[T])(using CpsMonadCoonversion[G,F], CpsMonadContext[F]): T
Using implementation of type class,
available in the current scope
transparent inline
def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T]
API (simpli
fi
ed)
Context function
trait FutureMonad extends CpsMonad[Future] {
type Context = FutureContex
}
async[Future] {
// provide API, aviable only inside async
summon[FutureContext].executionContext.submit(..)
......
}
transparent inline
def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T]
API (simpli
fi
ed)
trait CpsMonad[F[_]] {
type Context <: CpsMonadContext[F]
def pure[T](t:T):F[T]
def map[A,B](fa:F[A])(f: A=>B):F[B]
def flatMap[A,B](fa:F[A])(f: A=>F[B]):F[B]
def apply[T](op: Context => F[T]): F[T]
}
trait CpsTryMonad[F[_]] extends CpsMonad[F] {
def error[A](e: Throwable): F[A]
def flatMapTry[A,B](fa:F[A])(f: Try[A] => F[B
}
for. try/catch support
Transformations: (monadi
fi
cation, based on cps-transform)
CF[{a; b}]
F . flatMap(CF[a])(_ ⇒ CF[b])
rest in continuation passing style
Transformations: control-
fl
ow (monadi
fi
cation, based on cps-transform)
CF[{a; b}]
F . flatMap(CF[a])(_ ⇒ CF[b])
CF[t] : t ∈ Constant ∨ t ∈ Identifier
F . pure(t)
// rules for control-
fl
ow constructions are straightforward
CF[val a = b; c]
F . flatMap(CF[a])(a′

⇒ CF[bx/x′

])
CF[if a then b else c]
F . flatMap(CF[a])(a′

⇒ if (a′

) then CF[b] else CF[c])
CF[throw ex]
F . error(ex)
Transformations: control-
fl
ow, optimisations
F . flatMap(F . pure(a))(x ⇒ F . pure(b(x))
F . pure(b(a))
Two sequential synchronous fragments are merged into one:
Transformation of each control-
fl
ow construction are specialised again sync/async components :
if a then b else c CF[a] ≠ F . pure(a) ∧ (CF[b] ≠ F . pure(b) ∨ CF[c] ≠ F . pure(c))
CF[a] = F . pure(a) ∧ (CF[b] ≠ F . pure(b) ∨ CF[c] ≠ F . pure(c))
CF[a] = F . pure(a) ∧ CF[b] = F . pure(b) ∧ CF[c] = F . pure(c)
n(bounds) ~ n(awaits):
Performance == performance of concurrent framework.
Transformations: higher-order functions
class Cache[K,V] {
def getOrUpdate(k:K, whenAbsent: =>V): V
}
Call by name, synonym of ()=>V
async[Process]{
val k = retrieveKey(request)
cache.getOrUpdate(k, await(fetchValue(k)))
}
Usual answer: continuation support in runtime environment.
type(CF[(x : T)]) = F[T],  is not function 
type(CF[(x : A ⇒ B)]) = A ⇒ type(CF[B])
Problem: JVM Runtime (as Js and Native now) have no continuations support
Allow programmer to de
fi
ne async ‘shifted’ variant of function via typecalss.
Transformations: higher-order functions
class Cache[K,V] {
def getOrUpdate(k:K, whenAbsent: =>V): V
}
async[Process]{
val k = retrieveKey(request)
cache.getOrUpdate(k, await(fetchValue(k)))
}
class CacheAsyncShift[K,V] extends
AsyncShift[Cache[K,V]]{
def getOrUpdate[F[_]](o:Cache[K,V],m:CpsMonad[F])
(k:K, whenAbsent: ()=> F[V]):F[V] =
....
}
summon[AsyncCache[Cache[K,V]]].getOrUpdate[F](cache,monad)(k, ()=>fetchValue(k))
// where monad = summon[CpsMonad[F]]
Transformations: higher-order functions
class Cache[K,V] {
def getOrUpdate(k:K, whenAbsent: =>V): V
def getOrUpdateAsync[F[_]](m:CpsMonad[F])(k:K, whenAbsent: ()=>F[V]): F[V]
}
async[Process]{
val k = retrieveKey(request)
cache.getOrUpdate(k, await(fetchValue(k)))
}
cache.getOrUpdateAsync[F](monad)(k, ()=>fetchValue(k))
// where monad = summon[CpsMonad[F]]
// author aware about dotty-cps-async
substitution classes for chain of higher-order methods
class Collection[A] {
def map(f: A=>B): Collection[B]
def withFilter(p: A=>Boolean): FilteredCollection[A]
}
for { url <- urls if await(score(url)) > limit) }
yield await(fetchData(url))
urls.withFilter(url => await(score(url))>limit).map(await(fetchData(url)))
Developer expect that combination of map and
fi
lter will work at the same way, as in synchronous case.
Collection FilteredCollection Result
Element 1
Element 2
……..
substitution classes for chain of higher-order methods
class Collection[A] {
def map(f: A=>B): Collection[B]
def withFilter(p: A=>Boolean): FilteredCollection[A]
}
class FilteredCollectionAsyncSubst[F[_],A](m:CpsMonad[F])
extends CallChainAsyncShiftSubst[F, FilteredCollection[A], FilteredCollectionAsyncSubst[F,A]]:
def _finishChain: FilteredCollection[A]
def withFilter(p: A=> Boolean): this.type
def withFilterAsync(p: A=>F[Boolean]): this.type
def map[B](f: A => B): this.type
def mapAsync[B](f: A=>F[B]): this.type
class AsyncShiftCollectin extends AsyncShift[Collection[A]]:
def withFilter[F[_]](c:Collection[A],m:CpsMonad[F])
(p: A=>F[Boolean]): FilteredCollectionAsyncSubst[F,A]
//. accumulate all ho-methods in chain, interpret via _
fi
nishChain
//categorical interpretation — left Kan extension for FilteredCollection
Transformations:
class Collection[A] {
def map(f: A=>B): Collection[B]
def withFilter(p: A=>Boolean): FilteredCollection[A]
}
class FilteredCollectionAsyncSubst[F[_],A](m:CpsMonad[F])
extends CallChainAsyncShiftSubst[F, FilteredCollection[A], FilteredCollectionAsyncSubst[F,A]]:
def _finishChain: FilteredCollection[A]
def withFilter(p: A=> Boolean): this.type
def withFilterAsync(p: A=>F[Boolean]): this.type
def map[B](f: A => B): this.type
def mapAsync[B](f: A=>F[B]): this.type
class AsyncShiftCollectin extends AsyncShift[Collection[A]]:
def withFilter[F[_]](c:Collection[A],m:CpsMonad[F])
(p: A=>F[Boolean]): FilteredCollectionAsyncSubst[F,A]
//. accumulate all ho-methods in chain, interpret via _
fi
nishChain
//categorical interpretation — left Kan extension for FilteredCollection
substitution classes for chain of higher-order methods
class Collection[A] {
def map(f: A=>B): Collection[B]
def withFilter(p: A=>Boolean): FilteredCollection[A]
}
class FilteredCollectionAsyncSubst[F[_],A](m:CpsMonad[F])
extends CallChainAsyncShiftSubst[F, FilteredCollection[A], FilteredCollecti
def _finishChain: FilteredCollection[A]
def withFilter(p: A=> Boolean): this.type
def withFilterAsync(p: A=>F[Boolean]): this.type
def map[B](f: A => B): this.type
def mapAsync[B](f: A=>F[B]): this.type
//. accumulate all ho-methods in chain, interpret via _
fi
nishChain
//categorical interpretation — left Kan extension for FilteredCollection
urls.withFilter(url => await(score(url))>limit).map(await(fetchData(url)))
summon[AsynsChift[Collection[A]].
withFilterAsync(url => score(url).map(x => x>limit)).mapAsync(fetchData(url))
Automatic colouring.
async[IO] {
val r1 = cacheService.getOrUpdate(id,
await(talkToServer(id)))
val r2 = talkToServer(r1.data)
if (r2.isOk) then
writeToFile(r1.data)
IO.println("done")
true
else
IO.println("abort")
false
}
async[IO] {
val r1 = cacheService.getOrUpdate(id,
await(talkToServer(id)))
val r2 = talkToServer(r1.data)
if (await(r2).isOk) then
await(writeToFile(r1.data))
await(IO.println(“done”))
true
else
await(IO.println(“abort”))
false
}
x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T
discarded value F[T] →  discarded value await(F[T])
Automatic colouring.
async[IO] {
val r1 = cacheService.getOrUpdate(id,
await(talkToServer(id)))
val r2 = talkToServer(r1.data)
if (r2.isOk) then
writeToFile(r1.data)
IO.println("done")
true
else
IO.println("abort")
false
}
async[IO] {
val r1 = cacheService.getOrUpdate(id,
await(talkToServer(id)))
val r2 = talkToServer(r1.data)
if (await(r2).isOk) then
await(writeToFile(r1.data))
await(IO.println(“done”))
true
else
await(IO.println(“abort”))
false
}
x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T
discarded value F[T] →  discarded value await(F[T])
Problem: this can be unsafe for some type of monads.
// disabled by default, enabled by import
Automatic colouring.
x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T
discarded value F[T] →  discarded value await(F[T])
This can be unsafe for some type of monads:
def run(): F[Unit] = async[F] {
val connection = openConnection()
try
while
val command = readCommand(connection)
val reply = handle(command)
if (!reply.isMuted)
connection.send(reply.toBytes)
!command.isShutdown
do ()
finally
connection.close()
}
def run(): F[Unit] = async[F] {
val connection = openConnection()
try
while
val command = readCommand(await(connection))
val reply = handle(await(command))
if (!await(reply).isMuted)
await(connection).send(await(reply).toBytes)
!await(command).isShutdown
do ()
finally
await(connection).close()
}
F[_]. Is cached, I.e. two usages refers to the same instance — Safe. (Example: Future)
F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO)
Automatic colouring.
x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T
discarded value F[T] →  discarded value await(F[T])
This can be unsafe for some type of monads:
def run(): F[Unit] = async[F] {
val connection = openConnection()
try
while
val command = readCommand(connection)
val reply = handle(command)
if (!reply.isMuted)
connection.send(reply.toBytes)
!command.isShutdown
do ()
finally
connection.close()
}
def run(): F[Unit] = async[F] {
val connection = openConnection()
try
while
val command = readCommand(await(connection))
val reply = handle(await(command))
if (!await(reply).isMuted)
await(connection).send(await(reply).toBytes)
!await(command).isShutdown
do ()
finally
await(connection).close()
}
F[_]. Is cached, I.e. two usages refers to the same instance — Safe. (Example: Future)
F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO)
Automatic colouring.
x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T
discarded value F[T] →  discarded value await(F[T])
F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO)
memoize : F[T] ⇒ F[F[T]]
def run(): F[Unit] = async[F] {
val connection = await(memoize(openConnection()))
try
while
val command = await(memoize(readCommand(await(connection))))
val reply = await(memoize(handle(await(command))))
if (!await(reply).isMuted)
await(connection).send(await(reply).toBytes)
!await(command).isShutdown
do ()
finally
await(connection).close()
}
Automatic colouring.
x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T
discarded value F[T] →  discarded value await(F[T])
F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO)
Unsafe, when we mix synchronous and asynchronous usage.
memoize : F[T] ⇒ F[F[T]]
Preliminary code analysis two prevent such mixing:
v : F[T]var, U(v) − all usages of v
u ∈ U(V)
sync(u) ⟺ u ⊏ await(v)
async(u) ⟺ ¬sync(u) ∧ ¬(u ⊏ (x = v))
discarded(u)
u2 ⊏ (v1 = v2) ⇒ U(v1) ⊂ U(v2)
¬∃u1, u2 ∈ U(v) : sync(u1) ∧ async(u2)
Safety condition:
Patterns of practical usage:
- Migrating from scala2 SIP22 async/await to Scala3 with dotty-cps-async. (Chat-server)
- Monad: Future
- Utility server for integration of freeswitch with external database.
- Monad: [X] =>> Resource[IO,X]
- Stack [ postgres, skunk, http4s ].
- Port of scala library for implementing csp-channels. [scala-gopher]
- (Non-trivial usage, inline syntax sugar api inside async block)
- Monad: generic + ReadChannel
Issues:
- (near 1/2) are compiler issues.
- other: ergonomica and handling specialised cases.
https://github.com/rssh/dotty-cps-async
Ruslan Shevchenko, Kyiv, Ukraine.
<ruslan@shevchenko.kiev.ua>
proofspace.id
Embedding Generic Monadic Transformer into Scala.
{Questions ? }
https://github.com/rssh/dotty-cps-async

More Related Content

What's hot

TP Git avancé DevoxxFR 2018 (exercices)
TP Git avancé DevoxxFR 2018 (exercices)TP Git avancé DevoxxFR 2018 (exercices)
TP Git avancé DevoxxFR 2018 (exercices)
Jérôme Tamborini
 
Virtual Flink Forward 2020: A deep dive into Flink SQL - Jark Wu
Virtual Flink Forward 2020: A deep dive into Flink SQL - Jark WuVirtual Flink Forward 2020: A deep dive into Flink SQL - Jark Wu
Virtual Flink Forward 2020: A deep dive into Flink SQL - Jark Wu
Flink Forward
 
Introduction to Git/Github - A beginner's guide
Introduction to Git/Github - A beginner's guideIntroduction to Git/Github - A beginner's guide
Introduction to Git/Github - A beginner's guide
Rohit Arora
 
Creating_scheduled_reports_with_Zabbix.pdf
Creating_scheduled_reports_with_Zabbix.pdfCreating_scheduled_reports_with_Zabbix.pdf
Creating_scheduled_reports_with_Zabbix.pdf
ITDispendik
 
Introduction to Apache Flink
Introduction to Apache FlinkIntroduction to Apache Flink
Introduction to Apache Flink
mxmxm
 
Linux Kernel - Virtual File System
Linux Kernel - Virtual File SystemLinux Kernel - Virtual File System
Linux Kernel - Virtual File System
Adrian Huang
 
Booting Android: bootloaders, fastboot and boot images
Booting Android: bootloaders, fastboot and boot imagesBooting Android: bootloaders, fastboot and boot images
Booting Android: bootloaders, fastboot and boot images
Chris Simmonds
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4
ICS
 
Git
GitGit
Logical Volume Manager. An Introduction
Logical Volume Manager. An IntroductionLogical Volume Manager. An Introduction
Logical Volume Manager. An Introduction
Juan A. Suárez Romero
 
Clickhouse at Cloudflare. By Marek Vavrusa
Clickhouse at Cloudflare. By Marek VavrusaClickhouse at Cloudflare. By Marek Vavrusa
Clickhouse at Cloudflare. By Marek Vavrusa
Valery Tkachenko
 
Firefox OS Graphics inside
Firefox OS Graphics insideFirefox OS Graphics inside
Firefox OS Graphics inside
Sotaro Ikeda
 
Toolchain
ToolchainToolchain
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Flink Forward
 
Slab Allocator in Linux Kernel
Slab Allocator in Linux KernelSlab Allocator in Linux Kernel
Slab Allocator in Linux Kernel
Adrian Huang
 
GCC LTO
GCC LTOGCC LTO
Linux MMAP & Ioremap introduction
Linux MMAP & Ioremap introductionLinux MMAP & Ioremap introduction
Linux MMAP & Ioremap introduction
Gene Chang
 
Android Multimedia Framework
Android Multimedia FrameworkAndroid Multimedia Framework
Android Multimedia Framework
Picker Weng
 
Graph Gurus Episode 11: Accumulators for Complex Graph Analytics
Graph Gurus Episode 11: Accumulators for Complex Graph AnalyticsGraph Gurus Episode 11: Accumulators for Complex Graph Analytics
Graph Gurus Episode 11: Accumulators for Complex Graph Analytics
TigerGraph
 
GraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster EverywhereGraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster Everywhere
J On The Beach
 

What's hot (20)

TP Git avancé DevoxxFR 2018 (exercices)
TP Git avancé DevoxxFR 2018 (exercices)TP Git avancé DevoxxFR 2018 (exercices)
TP Git avancé DevoxxFR 2018 (exercices)
 
Virtual Flink Forward 2020: A deep dive into Flink SQL - Jark Wu
Virtual Flink Forward 2020: A deep dive into Flink SQL - Jark WuVirtual Flink Forward 2020: A deep dive into Flink SQL - Jark Wu
Virtual Flink Forward 2020: A deep dive into Flink SQL - Jark Wu
 
Introduction to Git/Github - A beginner's guide
Introduction to Git/Github - A beginner's guideIntroduction to Git/Github - A beginner's guide
Introduction to Git/Github - A beginner's guide
 
Creating_scheduled_reports_with_Zabbix.pdf
Creating_scheduled_reports_with_Zabbix.pdfCreating_scheduled_reports_with_Zabbix.pdf
Creating_scheduled_reports_with_Zabbix.pdf
 
Introduction to Apache Flink
Introduction to Apache FlinkIntroduction to Apache Flink
Introduction to Apache Flink
 
Linux Kernel - Virtual File System
Linux Kernel - Virtual File SystemLinux Kernel - Virtual File System
Linux Kernel - Virtual File System
 
Booting Android: bootloaders, fastboot and boot images
Booting Android: bootloaders, fastboot and boot imagesBooting Android: bootloaders, fastboot and boot images
Booting Android: bootloaders, fastboot and boot images
 
Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4Best Practices in Qt Quick/QML - Part 4
Best Practices in Qt Quick/QML - Part 4
 
Git
GitGit
Git
 
Logical Volume Manager. An Introduction
Logical Volume Manager. An IntroductionLogical Volume Manager. An Introduction
Logical Volume Manager. An Introduction
 
Clickhouse at Cloudflare. By Marek Vavrusa
Clickhouse at Cloudflare. By Marek VavrusaClickhouse at Cloudflare. By Marek Vavrusa
Clickhouse at Cloudflare. By Marek Vavrusa
 
Firefox OS Graphics inside
Firefox OS Graphics insideFirefox OS Graphics inside
Firefox OS Graphics inside
 
Toolchain
ToolchainToolchain
Toolchain
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
 
Slab Allocator in Linux Kernel
Slab Allocator in Linux KernelSlab Allocator in Linux Kernel
Slab Allocator in Linux Kernel
 
GCC LTO
GCC LTOGCC LTO
GCC LTO
 
Linux MMAP & Ioremap introduction
Linux MMAP & Ioremap introductionLinux MMAP & Ioremap introduction
Linux MMAP & Ioremap introduction
 
Android Multimedia Framework
Android Multimedia FrameworkAndroid Multimedia Framework
Android Multimedia Framework
 
Graph Gurus Episode 11: Accumulators for Complex Graph Analytics
Graph Gurus Episode 11: Accumulators for Complex Graph AnalyticsGraph Gurus Episode 11: Accumulators for Complex Graph Analytics
Graph Gurus Episode 11: Accumulators for Complex Graph Analytics
 
GraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster EverywhereGraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster Everywhere
 

Similar to Embedding Generic Monadic Transformer into Scala. [Tfp2022]

Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Ruslan Shevchenko
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystified
Alessandro Lacava
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
Hang Zhao
 
Go a crash course
Go   a crash courseGo   a crash course
Go a crash course
Eleanor McHugh
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
Romain Lecomte
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using Scala
Siarhiej Siemianchuk
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type Classes
Tapio Rautonen
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
Hang Zhao
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
kenbot
 
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
Wiem Zine Elabidine
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
Piotr Paradziński
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
Scalac
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetup
Mikhail Girkin
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
saintiss
 
Monadologie
MonadologieMonadologie
Monadologie
league
 
Essence of the iterator pattern
Essence of the iterator patternEssence of the iterator pattern
Essence of the iterator pattern
Markus Klink
 
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
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Peng Cheng
 
Asynchronous programming with java script and node.js
Asynchronous programming with java script and node.jsAsynchronous programming with java script and node.js
Asynchronous programming with java script and node.js
Timur Shemsedinov
 
Testing in the World of Functional Programming
Testing in the World of Functional ProgrammingTesting in the World of Functional Programming
Testing in the World of Functional Programming
Luka Jacobowitz
 

Similar to Embedding Generic Monadic Transformer into Scala. [Tfp2022] (20)

Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystified
 
Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
 
Go a crash course
Go   a crash courseGo   a crash course
Go a crash course
 
Un dsl pour ma base de données
Un dsl pour ma base de donnéesUn dsl pour ma base de données
Un dsl pour ma base de données
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using Scala
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type Classes
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adts
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monads
 
Berlin meetup
Berlin meetupBerlin meetup
Berlin meetup
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...Big picture of category theory in scala with deep dive into contravariant and...
Big picture of category theory in scala with deep dive into contravariant and...
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetup
 
Machine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting ConcernsMachine-level Composition of Modularized Crosscutting Concerns
Machine-level Composition of Modularized Crosscutting Concerns
 
Monadologie
MonadologieMonadologie
Monadologie
 
Essence of the iterator pattern
Essence of the iterator patternEssence of the iterator pattern
Essence of the iterator pattern
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free Monads
 
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
Shape Safety in Tensor Programming is Easy for a Theorem Prover -SBTB 2021
 
Asynchronous programming with java script and node.js
Asynchronous programming with java script and node.jsAsynchronous programming with java script and node.js
Asynchronous programming with java script and node.js
 
Testing in the World of Functional Programming
Testing in the World of Functional ProgrammingTesting in the World of Functional Programming
Testing in the World of Functional Programming
 

More from Ruslan Shevchenko

Svitla talks 2021_03_25
Svitla talks 2021_03_25Svitla talks 2021_03_25
Svitla talks 2021_03_25
Ruslan Shevchenko
 
Akka / Lts behavior
Akka / Lts behaviorAkka / Lts behavior
Akka / Lts behavior
Ruslan Shevchenko
 
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Papers We Love / Kyiv :  PAXOS (and little about other consensuses )Papers We Love / Kyiv :  PAXOS (and little about other consensuses )
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Ruslan Shevchenko
 
Scala / Technology evolution
Scala  / Technology evolutionScala  / Technology evolution
Scala / Technology evolution
Ruslan Shevchenko
 
{co/contr} variance from LSP
{co/contr} variance  from LSP{co/contr} variance  from LSP
{co/contr} variance from LSP
Ruslan Shevchenko
 
N flavors of streaming
N flavors of streamingN flavors of streaming
N flavors of streaming
Ruslan Shevchenko
 
SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.
Ruslan Shevchenko
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scala
Ruslan Shevchenko
 
Why scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with thisWhy scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with this
Ruslan Shevchenko
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
Ruslan Shevchenko
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applications
Ruslan Shevchenko
 
Csp scala wixmeetup2016
Csp scala wixmeetup2016Csp scala wixmeetup2016
Csp scala wixmeetup2016
Ruslan Shevchenko
 
IDLs
IDLsIDLs
R ext world/ useR! Kiev
R ext world/ useR!  KievR ext world/ useR!  Kiev
R ext world/ useR! Kiev
Ruslan Shevchenko
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platform
Ruslan Shevchenko
 
Behind OOD: domain modelling in post-OO world.
Behind OOD:  domain modelling in post-OO world.Behind OOD:  domain modelling in post-OO world.
Behind OOD: domain modelling in post-OO world.
Ruslan Shevchenko
 
scala-gopher: async implementation of CSP for scala
scala-gopher:  async implementation of CSP  for  scalascala-gopher:  async implementation of CSP  for  scala
scala-gopher: async implementation of CSP for scala
Ruslan Shevchenko
 
Programming Languages: some news for the last N years
Programming Languages: some news for the last N yearsProgramming Languages: some news for the last N years
Programming Languages: some news for the last N years
Ruslan Shevchenko
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
Ruslan Shevchenko
 
Ruslan.shevchenko: most functional-day-kiev 2014
Ruslan.shevchenko: most functional-day-kiev 2014Ruslan.shevchenko: most functional-day-kiev 2014
Ruslan.shevchenko: most functional-day-kiev 2014
Ruslan Shevchenko
 

More from Ruslan Shevchenko (20)

Svitla talks 2021_03_25
Svitla talks 2021_03_25Svitla talks 2021_03_25
Svitla talks 2021_03_25
 
Akka / Lts behavior
Akka / Lts behaviorAkka / Lts behavior
Akka / Lts behavior
 
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Papers We Love / Kyiv :  PAXOS (and little about other consensuses )Papers We Love / Kyiv :  PAXOS (and little about other consensuses )
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
 
Scala / Technology evolution
Scala  / Technology evolutionScala  / Technology evolution
Scala / Technology evolution
 
{co/contr} variance from LSP
{co/contr} variance  from LSP{co/contr} variance  from LSP
{co/contr} variance from LSP
 
N flavors of streaming
N flavors of streamingN flavors of streaming
N flavors of streaming
 
SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.SE 20016 - programming languages landscape.
SE 20016 - programming languages landscape.
 
Few simple-type-tricks in scala
Few simple-type-tricks in scalaFew simple-type-tricks in scala
Few simple-type-tricks in scala
 
Why scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with thisWhy scala is not my ideal language and what I can do with this
Why scala is not my ideal language and what I can do with this
 
Scala jargon cheatsheet
Scala jargon cheatsheetScala jargon cheatsheet
Scala jargon cheatsheet
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applications
 
Csp scala wixmeetup2016
Csp scala wixmeetup2016Csp scala wixmeetup2016
Csp scala wixmeetup2016
 
IDLs
IDLsIDLs
IDLs
 
R ext world/ useR! Kiev
R ext world/ useR!  KievR ext world/ useR!  Kiev
R ext world/ useR! Kiev
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platform
 
Behind OOD: domain modelling in post-OO world.
Behind OOD:  domain modelling in post-OO world.Behind OOD:  domain modelling in post-OO world.
Behind OOD: domain modelling in post-OO world.
 
scala-gopher: async implementation of CSP for scala
scala-gopher:  async implementation of CSP  for  scalascala-gopher:  async implementation of CSP  for  scala
scala-gopher: async implementation of CSP for scala
 
Programming Languages: some news for the last N years
Programming Languages: some news for the last N yearsProgramming Languages: some news for the last N years
Programming Languages: some news for the last N years
 
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
JDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation streamJDays Lviv 2014:  Java8 vs Scala:  Difference points & innovation stream
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
 
Ruslan.shevchenko: most functional-day-kiev 2014
Ruslan.shevchenko: most functional-day-kiev 2014Ruslan.shevchenko: most functional-day-kiev 2014
Ruslan.shevchenko: most functional-day-kiev 2014
 

Recently uploaded

SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
Hironori Washizaki
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Undress Baby
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
pavan998932
 
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
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
DDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systemsDDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systems
Gerardo Pardo-Castellote
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
Google
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
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
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 

Recently uploaded (20)

SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024SWEBOK and Education at FUSE Okinawa 2024
SWEBOK and Education at FUSE Okinawa 2024
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
 
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
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
DDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systemsDDS-Security 1.2 - What's New? Stronger security for long-running systems
DDS-Security 1.2 - What's New? Stronger security for long-running systems
 
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppAI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
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)
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 

Embedding Generic Monadic Transformer into Scala. [Tfp2022]

  • 1. Ruslan Shevchenko, Kyiv, Ukraine. <ruslan@shevchenko.kiev.ua> proofspace.id Embedding Generic Monadic Transformer into Scala. {Can we return concurrent programming into mainstream? } https://github.com/rssh/dotty-cps-async
  • 2. Asynchronous control flow - Scala industrial usage. for{ r1 <- cacheService.get(id) match case Some(v) => IO.success(v) case None => talkToServer(id).map{v => cacheService.update(id,v) v } r2 <- talkToServer(r1.data) result <- if (r2.isOk) then { writeToFile(resultData) >>= IO.println("done") >>= true } else { IO.println("abort") >>= false } } yield result Monadic DSL on top of some effect system or. Future
  • 3. Asynchronous control flow - Scala industrial usage. for{ r1 <- cacheService.get(id) match case Some(v) => IO.success(v) case None => talkToServer(id).map{v => cacheService.update(id,v) v } R2 <- talkToServer(r1.data) result <- if (r2.isOk) then { writeToFile(r1.data) >>= IO.println("done") >>= true } else { IO.println("abort") >>= false } } yield result Monadic DSL on top of some effect system or. Future async[IO] { val r1 = cacheService.getOrUpdate(id, await(talkToServer(id))) val r2 = talkToServer(r1.data) if (r2.isOk) then writeToFile(r1.data) IO.println("done") true else IO.println("abort") false } "Mainstream" Control-Flow over some effect system or Future
  • 4. API (simpli fi ed) Well-known async/await interface. + - generic monad - ability to use higher-order functions without runtime support for continuations. - automatic colouring (awaits can-be omitted if can be restored from the context) def async[F[_]](f: T):F[T] def await[F[_]](f: F[T]):T
  • 5. transparent inline def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T] API (simpli fi ed) @compileTimeOnly("await should be inside async block") def await[G[_],T,F[_]](f: G[T])(using CpsMonadConversion[G,F], CpsMonadContext[F]): //in real signature here is temporary class, to allow currying of type parameters def async[F[_]](f: T):F[T] def await[F[_]](f: F[T]):T
  • 6. transparent inline def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T] API (simpli fi ed) @compileTimeOnly("await should be inside async block") def await[G[_],T,F[_]](f: G[T])(using CpsMonadConversion[G,F], CpsMonadContext[F]): T Macro, evaluated during typing
  • 7. transparent inline def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T] API (simpli fi ed) @compileTimeOnly("await should be inside async block") def await[G[_],T,F[_]](f: G[T])(using CpsMonadCoversion[G,F], CpsMonadContext[F]): T F[_]. — Our monad : Future[T], IO[T], … etc G[_]. — Monad which we await
  • 8. transparent inline def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T] API (simpli fi ed) @compileTimeOnly("await should be inside async block") def await[G[_],T,F[_]](f: G[T])(using CpsMonadCoonversion[G,F], CpsMonadContext[F]): T Using implementation of type class, available in the current scope
  • 9. transparent inline def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T] API (simpli fi ed) Context function trait FutureMonad extends CpsMonad[Future] { type Context = FutureContex } async[Future] { // provide API, aviable only inside async summon[FutureContext].executionContext.submit(..) ...... }
  • 10. transparent inline def async[F[_]](using am: CpsMonad[F])[T](inline f: am.Context ?=> T):F[T] API (simpli fi ed) trait CpsMonad[F[_]] { type Context <: CpsMonadContext[F] def pure[T](t:T):F[T] def map[A,B](fa:F[A])(f: A=>B):F[B] def flatMap[A,B](fa:F[A])(f: A=>F[B]):F[B] def apply[T](op: Context => F[T]): F[T] } trait CpsTryMonad[F[_]] extends CpsMonad[F] { def error[A](e: Throwable): F[A] def flatMapTry[A,B](fa:F[A])(f: Try[A] => F[B } for. try/catch support
  • 11. Transformations: (monadi fi cation, based on cps-transform) CF[{a; b}] F . flatMap(CF[a])(_ ⇒ CF[b]) rest in continuation passing style
  • 12. Transformations: control- fl ow (monadi fi cation, based on cps-transform) CF[{a; b}] F . flatMap(CF[a])(_ ⇒ CF[b]) CF[t] : t ∈ Constant ∨ t ∈ Identifier F . pure(t) // rules for control- fl ow constructions are straightforward CF[val a = b; c] F . flatMap(CF[a])(a′  ⇒ CF[bx/x′  ]) CF[if a then b else c] F . flatMap(CF[a])(a′  ⇒ if (a′  ) then CF[b] else CF[c]) CF[throw ex] F . error(ex)
  • 13. Transformations: control- fl ow, optimisations F . flatMap(F . pure(a))(x ⇒ F . pure(b(x)) F . pure(b(a)) Two sequential synchronous fragments are merged into one: Transformation of each control- fl ow construction are specialised again sync/async components : if a then b else c CF[a] ≠ F . pure(a) ∧ (CF[b] ≠ F . pure(b) ∨ CF[c] ≠ F . pure(c)) CF[a] = F . pure(a) ∧ (CF[b] ≠ F . pure(b) ∨ CF[c] ≠ F . pure(c)) CF[a] = F . pure(a) ∧ CF[b] = F . pure(b) ∧ CF[c] = F . pure(c) n(bounds) ~ n(awaits): Performance == performance of concurrent framework.
  • 14. Transformations: higher-order functions class Cache[K,V] { def getOrUpdate(k:K, whenAbsent: =>V): V } Call by name, synonym of ()=>V async[Process]{ val k = retrieveKey(request) cache.getOrUpdate(k, await(fetchValue(k))) } Usual answer: continuation support in runtime environment. type(CF[(x : T)]) = F[T],  is not function  type(CF[(x : A ⇒ B)]) = A ⇒ type(CF[B]) Problem: JVM Runtime (as Js and Native now) have no continuations support Allow programmer to de fi ne async ‘shifted’ variant of function via typecalss.
  • 15. Transformations: higher-order functions class Cache[K,V] { def getOrUpdate(k:K, whenAbsent: =>V): V } async[Process]{ val k = retrieveKey(request) cache.getOrUpdate(k, await(fetchValue(k))) } class CacheAsyncShift[K,V] extends AsyncShift[Cache[K,V]]{ def getOrUpdate[F[_]](o:Cache[K,V],m:CpsMonad[F]) (k:K, whenAbsent: ()=> F[V]):F[V] = .... } summon[AsyncCache[Cache[K,V]]].getOrUpdate[F](cache,monad)(k, ()=>fetchValue(k)) // where monad = summon[CpsMonad[F]]
  • 16. Transformations: higher-order functions class Cache[K,V] { def getOrUpdate(k:K, whenAbsent: =>V): V def getOrUpdateAsync[F[_]](m:CpsMonad[F])(k:K, whenAbsent: ()=>F[V]): F[V] } async[Process]{ val k = retrieveKey(request) cache.getOrUpdate(k, await(fetchValue(k))) } cache.getOrUpdateAsync[F](monad)(k, ()=>fetchValue(k)) // where monad = summon[CpsMonad[F]] // author aware about dotty-cps-async
  • 17. substitution classes for chain of higher-order methods class Collection[A] { def map(f: A=>B): Collection[B] def withFilter(p: A=>Boolean): FilteredCollection[A] } for { url <- urls if await(score(url)) > limit) } yield await(fetchData(url)) urls.withFilter(url => await(score(url))>limit).map(await(fetchData(url))) Developer expect that combination of map and fi lter will work at the same way, as in synchronous case. Collection FilteredCollection Result Element 1 Element 2 ……..
  • 18. substitution classes for chain of higher-order methods class Collection[A] { def map(f: A=>B): Collection[B] def withFilter(p: A=>Boolean): FilteredCollection[A] } class FilteredCollectionAsyncSubst[F[_],A](m:CpsMonad[F]) extends CallChainAsyncShiftSubst[F, FilteredCollection[A], FilteredCollectionAsyncSubst[F,A]]: def _finishChain: FilteredCollection[A] def withFilter(p: A=> Boolean): this.type def withFilterAsync(p: A=>F[Boolean]): this.type def map[B](f: A => B): this.type def mapAsync[B](f: A=>F[B]): this.type class AsyncShiftCollectin extends AsyncShift[Collection[A]]: def withFilter[F[_]](c:Collection[A],m:CpsMonad[F]) (p: A=>F[Boolean]): FilteredCollectionAsyncSubst[F,A] //. accumulate all ho-methods in chain, interpret via _ fi nishChain //categorical interpretation — left Kan extension for FilteredCollection
  • 19. Transformations: class Collection[A] { def map(f: A=>B): Collection[B] def withFilter(p: A=>Boolean): FilteredCollection[A] } class FilteredCollectionAsyncSubst[F[_],A](m:CpsMonad[F]) extends CallChainAsyncShiftSubst[F, FilteredCollection[A], FilteredCollectionAsyncSubst[F,A]]: def _finishChain: FilteredCollection[A] def withFilter(p: A=> Boolean): this.type def withFilterAsync(p: A=>F[Boolean]): this.type def map[B](f: A => B): this.type def mapAsync[B](f: A=>F[B]): this.type class AsyncShiftCollectin extends AsyncShift[Collection[A]]: def withFilter[F[_]](c:Collection[A],m:CpsMonad[F]) (p: A=>F[Boolean]): FilteredCollectionAsyncSubst[F,A] //. accumulate all ho-methods in chain, interpret via _ fi nishChain //categorical interpretation — left Kan extension for FilteredCollection
  • 20. substitution classes for chain of higher-order methods class Collection[A] { def map(f: A=>B): Collection[B] def withFilter(p: A=>Boolean): FilteredCollection[A] } class FilteredCollectionAsyncSubst[F[_],A](m:CpsMonad[F]) extends CallChainAsyncShiftSubst[F, FilteredCollection[A], FilteredCollecti def _finishChain: FilteredCollection[A] def withFilter(p: A=> Boolean): this.type def withFilterAsync(p: A=>F[Boolean]): this.type def map[B](f: A => B): this.type def mapAsync[B](f: A=>F[B]): this.type //. accumulate all ho-methods in chain, interpret via _ fi nishChain //categorical interpretation — left Kan extension for FilteredCollection urls.withFilter(url => await(score(url))>limit).map(await(fetchData(url))) summon[AsynsChift[Collection[A]]. withFilterAsync(url => score(url).map(x => x>limit)).mapAsync(fetchData(url))
  • 21. Automatic colouring. async[IO] { val r1 = cacheService.getOrUpdate(id, await(talkToServer(id))) val r2 = talkToServer(r1.data) if (r2.isOk) then writeToFile(r1.data) IO.println("done") true else IO.println("abort") false } async[IO] { val r1 = cacheService.getOrUpdate(id, await(talkToServer(id))) val r2 = talkToServer(r1.data) if (await(r2).isOk) then await(writeToFile(r1.data)) await(IO.println(“done”)) true else await(IO.println(“abort”)) false } x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T discarded value F[T] →  discarded value await(F[T])
  • 22. Automatic colouring. async[IO] { val r1 = cacheService.getOrUpdate(id, await(talkToServer(id))) val r2 = talkToServer(r1.data) if (r2.isOk) then writeToFile(r1.data) IO.println("done") true else IO.println("abort") false } async[IO] { val r1 = cacheService.getOrUpdate(id, await(talkToServer(id))) val r2 = talkToServer(r1.data) if (await(r2).isOk) then await(writeToFile(r1.data)) await(IO.println(“done”)) true else await(IO.println(“abort”)) false } x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T discarded value F[T] →  discarded value await(F[T]) Problem: this can be unsafe for some type of monads. // disabled by default, enabled by import
  • 23. Automatic colouring. x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T discarded value F[T] →  discarded value await(F[T]) This can be unsafe for some type of monads: def run(): F[Unit] = async[F] { val connection = openConnection() try while val command = readCommand(connection) val reply = handle(command) if (!reply.isMuted) connection.send(reply.toBytes) !command.isShutdown do () finally connection.close() } def run(): F[Unit] = async[F] { val connection = openConnection() try while val command = readCommand(await(connection)) val reply = handle(await(command)) if (!await(reply).isMuted) await(connection).send(await(reply).toBytes) !await(command).isShutdown do () finally await(connection).close() } F[_]. Is cached, I.e. two usages refers to the same instance — Safe. (Example: Future) F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO)
  • 24. Automatic colouring. x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T discarded value F[T] →  discarded value await(F[T]) This can be unsafe for some type of monads: def run(): F[Unit] = async[F] { val connection = openConnection() try while val command = readCommand(connection) val reply = handle(command) if (!reply.isMuted) connection.send(reply.toBytes) !command.isShutdown do () finally connection.close() } def run(): F[Unit] = async[F] { val connection = openConnection() try while val command = readCommand(await(connection)) val reply = handle(await(command)) if (!await(reply).isMuted) await(connection).send(await(reply).toBytes) !await(command).isShutdown do () finally await(connection).close() } F[_]. Is cached, I.e. two usages refers to the same instance — Safe. (Example: Future) F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO)
  • 25. Automatic colouring. x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T discarded value F[T] →  discarded value await(F[T]) F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO) memoize : F[T] ⇒ F[F[T]] def run(): F[Unit] = async[F] { val connection = await(memoize(openConnection())) try while val command = await(memoize(readCommand(await(connection)))) val reply = await(memoize(handle(await(command)))) if (!await(reply).isMuted) await(connection).send(await(reply).toBytes) !await(command).isShutdown do () finally await(connection).close() }
  • 26. Automatic colouring. x : F[T]) → await(x) : T . implicit conversion:F[T] ⇒ T discarded value F[T] →  discarded value await(F[T]) F[_]. Is effect, I.e. two usage produce two effect — Unsafe. (Example: IO) Unsafe, when we mix synchronous and asynchronous usage. memoize : F[T] ⇒ F[F[T]] Preliminary code analysis two prevent such mixing: v : F[T]var, U(v) − all usages of v u ∈ U(V) sync(u) ⟺ u ⊏ await(v) async(u) ⟺ ¬sync(u) ∧ ¬(u ⊏ (x = v)) discarded(u) u2 ⊏ (v1 = v2) ⇒ U(v1) ⊂ U(v2) ¬∃u1, u2 ∈ U(v) : sync(u1) ∧ async(u2) Safety condition:
  • 27. Patterns of practical usage: - Migrating from scala2 SIP22 async/await to Scala3 with dotty-cps-async. (Chat-server) - Monad: Future - Utility server for integration of freeswitch with external database. - Monad: [X] =>> Resource[IO,X] - Stack [ postgres, skunk, http4s ]. - Port of scala library for implementing csp-channels. [scala-gopher] - (Non-trivial usage, inline syntax sugar api inside async block) - Monad: generic + ReadChannel Issues: - (near 1/2) are compiler issues. - other: ergonomica and handling specialised cases. https://github.com/rssh/dotty-cps-async
  • 28. Ruslan Shevchenko, Kyiv, Ukraine. <ruslan@shevchenko.kiev.ua> proofspace.id Embedding Generic Monadic Transformer into Scala. {Questions ? } https://github.com/rssh/dotty-cps-async