SlideShare ist ein Scribd-Unternehmen logo
1 von 28
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Pointers and Dynamic Memory Allocation
Pointers and Dynamic Memory AllocationPointers and Dynamic Memory Allocation
Pointers and Dynamic Memory AllocationRabin BK
 
Principal of objected oriented programming
Principal of objected oriented programming Principal of objected oriented programming
Principal of objected oriented programming Rokonuzzaman Rony
 
Functions in python
Functions in pythonFunctions in python
Functions in pythoncolorsof
 
Primitive data types in java
Primitive data types in javaPrimitive data types in java
Primitive data types in javaUmamaheshwariv1
 
String functions and operations
String functions and operations String functions and operations
String functions and operations Mudasir Syed
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Philip Schwarz
 
Python Data Structures and Algorithms.pptx
Python Data Structures and Algorithms.pptxPython Data Structures and Algorithms.pptx
Python Data Structures and Algorithms.pptxShreyasLawand
 
Python oop - class 2 (inheritance)
Python   oop - class 2 (inheritance)Python   oop - class 2 (inheritance)
Python oop - class 2 (inheritance)Aleksander Fabijan
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside💡 Tomasz Kogut
 
SPL 1 | Introduction to Structured programming language
SPL 1 | Introduction to Structured programming languageSPL 1 | Introduction to Structured programming language
SPL 1 | Introduction to Structured programming languageMohammad Imam Hossain
 
C Programming Storage classes, Recursion
C Programming Storage classes, RecursionC Programming Storage classes, Recursion
C Programming Storage classes, RecursionSreedhar Chowdam
 
Classes and objects1
Classes and objects1Classes and objects1
Classes and objects1Vineeta Garg
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
Theory of first order logic
Theory of first order logicTheory of first order logic
Theory of first order logicDevaddd
 

Was ist angesagt? (20)

ZIO Queue
ZIO QueueZIO Queue
ZIO Queue
 
Pointers and Dynamic Memory Allocation
Pointers and Dynamic Memory AllocationPointers and Dynamic Memory Allocation
Pointers and Dynamic Memory Allocation
 
Java Strings
Java StringsJava Strings
Java Strings
 
Principal of objected oriented programming
Principal of objected oriented programming Principal of objected oriented programming
Principal of objected oriented programming
 
Functions in python
Functions in pythonFunctions in python
Functions in python
 
Primitive data types in java
Primitive data types in javaPrimitive data types in java
Primitive data types in java
 
String functions and operations
String functions and operations String functions and operations
String functions and operations
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 1
 
Python Data Structures and Algorithms.pptx
Python Data Structures and Algorithms.pptxPython Data Structures and Algorithms.pptx
Python Data Structures and Algorithms.pptx
 
Python oop - class 2 (inheritance)
Python   oop - class 2 (inheritance)Python   oop - class 2 (inheritance)
Python oop - class 2 (inheritance)
 
Taking your side effects aside
Taking your side effects asideTaking your side effects aside
Taking your side effects aside
 
Constructors and destructors
Constructors and destructorsConstructors and destructors
Constructors and destructors
 
SPL 1 | Introduction to Structured programming language
SPL 1 | Introduction to Structured programming languageSPL 1 | Introduction to Structured programming language
SPL 1 | Introduction to Structured programming language
 
C Programming Storage classes, Recursion
C Programming Storage classes, RecursionC Programming Storage classes, Recursion
C Programming Storage classes, Recursion
 
Classes and objects1
Classes and objects1Classes and objects1
Classes and objects1
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Theory of first order logic
Theory of first order logicTheory of first order logic
Theory of first order logic
 
cs8251 unit 1 ppt
cs8251 unit 1 pptcs8251 unit 1 ppt
cs8251 unit 1 ppt
 
Preparing for Scala 3
Preparing for Scala 3Preparing for Scala 3
Preparing for Scala 3
 
Functions in python
Functions in python Functions in python
Functions in python
 

Ähnlich wie 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 demystifiedAlessandro 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 2Hang Zhao
 
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éesRomain Lecomte
 
Concurrent Application Development using Scala
Concurrent Application Development using ScalaConcurrent Application Development using Scala
Concurrent Application Development using ScalaSiarhiej Siemianchuk
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type ClassesTapio Rautonen
 
Fp in scala with adts
Fp in scala with adtsFp in scala with adts
Fp in scala with adtsHang Zhao
 
Running Free with the Monads
Running Free with the MonadsRunning Free with the Monads
Running Free with the Monadskenbot
 
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
 
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
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetupMikhail 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 Concernssaintiss
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
Essence of the iterator pattern
Essence of the iterator patternEssence of the iterator pattern
Essence of the iterator patternMarkus Klink
 
Post-Free: Life After Free Monads
Post-Free: Life After Free MonadsPost-Free: Life After Free Monads
Post-Free: Life After Free MonadsJohn 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 2021Peng 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.jsTimur 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 ProgrammingLuka Jacobowitz
 

Ähnlich wie 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
 

Mehr von 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 evolutionRuslan Shevchenko
 
{co/contr} variance from LSP
{co/contr} variance  from LSP{co/contr} variance  from LSP
{co/contr} variance from LSPRuslan 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 scalaRuslan 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 thisRuslan Shevchenko
 
Java & low latency applications
Java & low latency applicationsJava & low latency applications
Java & low latency applicationsRuslan Shevchenko
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platformRuslan 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 scalaRuslan 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 yearsRuslan 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 streamRuslan 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 2014Ruslan Shevchenko
 

Mehr von 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
 

Kürzlich hochgeladen

React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptrcbcrtm
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfkalichargn70th171
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmSujith Sukumaran
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 

Kürzlich hochgeladen (20)

React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
cpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.pptcpct NetworkING BASICS AND NETWORK TOOL.ppt
cpct NetworkING BASICS AND NETWORK TOOL.ppt
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdfExploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
Exploring Selenium_Appium Frameworks for Seamless Integration with HeadSpin.pdf
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
Intelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalmIntelligent Home Wi-Fi Solutions | ThinkPalm
Intelligent Home Wi-Fi Solutions | ThinkPalm
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 

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