Interpreters and you Mark Mynsted, @mmynsted Dave Gurnell, - - PowerPoint PPT Presentation

interpreters and you
SMART_READER_LITE
LIVE PREVIEW

Interpreters and you Mark Mynsted, @mmynsted Dave Gurnell, - - PowerPoint PPT Presentation

Interpreters and you Mark Mynsted, @mmynsted Dave Gurnell, @davegurnell Interpreters and you Mark Mynsted, @mmynsted Dave Gurnell, @davegurnell Interpreters and you Dave Gurnell, @davegurnell Mark Mynsted, @mmynsted Interpreters and you


slide-1
SLIDE 1

Interpreters and you

Mark Mynsted, @mmynsted Dave Gurnell, @davegurnell

slide-2
SLIDE 2

Interpreters and you

Mark Mynsted, @mmynsted Dave Gurnell, @davegurnell

slide-3
SLIDE 3

Interpreters and you

Dave Gurnell, @davegurnell Mark Mynsted, @mmynsted

slide-4
SLIDE 4

Interpreters and you

Mark Mynsted, @mmynsted Dave Gurnell, @davegurnell

slide-5
SLIDE 5
slide-6
SLIDE 6
slide-7
SLIDE 7

Scala

slide-8
SLIDE 8

Scala Result

slide-9
SLIDE 9

DSL Result

slide-10
SLIDE 10

Interpreter Program Result

slide-11
SLIDE 11

Program 1 Program 3 Result 1 Result 3 Program Result Interpreter

Structure Implementa?on

slide-12
SLIDE 12

Interpreter Program 2 Result 2 Program 1 Program 3 Result 1 Result 3

slide-13
SLIDE 13

Program

Interpreter 2 Interpreter 1 Interpreter 3

Result 1 Result 3 Result 2

slide-14
SLIDE 14

Program

Type
 checker

PreCy
 printer “Explain”
 command

Code Execu?on
 plan Types

slide-15
SLIDE 15

Program

Async
 interpreter

Interpreter Sandboxed
 interpreter

Result Result or
 failure Future

slide-16
SLIDE 16

Program

Compiler

Program

slide-17
SLIDE 17
  • 1. Re-use interpreters

  • 2. Mul?ple interpreters
  • 3. Abstract over effects

( 4. Inspect / rewrite / compile programs )

slide-18
SLIDE 18

Big approaches

slide-19
SLIDE 19

Model programs as data


Model programs as sets of method calls

Reifica?on Church encoding

slide-20
SLIDE 20

Model programs as data


Model programs as sets of method calls

Reifica?on Free Tagless final Church encoding

slide-21
SLIDE 21

Standalone Embedded

slide-22
SLIDE 22

Standalone Embedded

Completely custom Independent of host language Align with host language Reuse host language features

slide-23
SLIDE 23

Reified encodings

slide-24
SLIDE 24

A calculated example

slide-25
SLIDE 25

(1 + 2) * (3 + 4)

slide-26
SLIDE 26

val program = () =? (1 + 2) * (3 + 4)

slide-27
SLIDE 27

val program = () =? (1 + 2) * (3 + 4) program() /0 res0: Int = 21

slide-28
SLIDE 28

val program = () =? (1 + 2) * (3 + 4) def eval(prog: () =? Int): Int = ???

slide-29
SLIDE 29

val program = () =? (1 + 2) * (3 + 4) def eval(prog: () =? Int): Int = prog()

slide-30
SLIDE 30

sealed trait Expr case class Lit(value: Int) extends Expr case class Add(a: Expr, b: Expr) extends Expr case class Mul(a: Expr, b: Expr) extends Expr

slide-31
SLIDE 31

sealed trait Expr case class Lit(value: Int) extends Expr case class Add(a: Expr, b: Expr) extends Expr case class Mul(a: Expr, b: Expr) extends Expr val program: Expr = Mul(Add(Lit(1), Lit(2)), Add(Lit(3), Lit(4)))

slide-32
SLIDE 32

sealed trait Expr case class Lit(value: Int) extends Expr case class Add(a: Expr, b: Expr) extends Expr case class Mul(a: Expr, b: Expr) extends Expr val program: Expr = Mul(Add(Lit(1), Lit(2)), Add(Lit(3), Lit(4))) def eval(expr: Expr): Int = expr match { case Lit(value) =? value case Add(a, b) =? eval(a) + eval(b) case Mul(a, b) =? eval(a) * eval(b) } eval(program) /0 res0: Int = 21

slide-33
SLIDE 33

def eval(expr: Expr): Int = expr match { case Lit(value) =? value case Add(a, b) =? eval(a) + eval(b) case Mul(a, b) =? eval(a) * eval(b) }

slide-34
SLIDE 34

def evalAsync(expr: Expr): Future[Int] = expr match { case Lit(value) =? Future.successful(value) case Add(a, b) =? val x = evalAsync(a) val y = evalAsync(b) x.flatMap(a =? y.map(b =? a + b)) case Mul(a, b) =? val x = evalAsync(a) val y = evalAsync(b) x.flatMap(a =? y.map(b =? a * b)) }

slide-35
SLIDE 35

def prettyPrint(expr: Expr): String = expr match { case Lit(value) =? value.toString case Add(a, b) =? s"${prettyPrint(a)} + ${prettyPrint(b)}" case Mul(a, b) =? s"${prettyPrint(a)} * ${prettyPrint(b)}" }

slide-36
SLIDE 36

def simplify(expr: Expr): Expr = expr match { case Mul(a, Add(b, c)) =? simplify(Add(Mul(a, b), Mul(a, c))) case Mul(Add(a, b), c) =? simplify(Add(Mul(a, c), Mul(b, c))) case Mul(a, b) =? Mul(simplify(a), simplify(b)) case Add(a, b) =? Add(simplify(a), simplify(b)) case Lit(v) =? Lit(v) }

slide-37
SLIDE 37

Simplify the language 
 Empower the interpreter

slide-38
SLIDE 38

Constraints liberate
 Liberty constrains

slide-39
SLIDE 39

What about types?

slide-40
SLIDE 40

Untyped DSLs

slide-41
SLIDE 41

1 < 2 &' 3 < 4

slide-42
SLIDE 42

sealed trait Expr case class Lit(value: Int) extends Expr case class Lt(a: Expr, b: Expr) extends Expr case class And(a: Expr, b: Expr) extends Expr

slide-43
SLIDE 43

val validProgram: Expr = And(Lt(Lit(1), Lit(2)), Lt(Lit(3), Lit(4)))

slide-44
SLIDE 44

val invalidProgram: Expr = Lt(And(Lit(1), Lit(2)), And(Lit(3), Lit(4)))

slide-45
SLIDE 45

def eval(program: Expr): ??? = ???

slide-46
SLIDE 46

def eval(program: Expr): ??? = ???

Boolean or integer expression ?

slide-47
SLIDE 47

def eval(program: Expr): ??? = ???

Boolean or integer expression ? Model errors here ?

slide-48
SLIDE 48

def eval(program: Expr): ??? = program match { case Lit(n) =? ??? case Lt(a, b) =? ??? case And(a, b) =? ??? }

Are sub-expressions the right type? Boolean or integer expression ? Model errors here ?

slide-49
SLIDE 49

def eval(program: Expr): Either[Error, ???] = program match { case Lit(n) =? ??? case Lt(a, b) =? ??? case And(a, b) =? ??? }

Boolean or integer expression ? Are sub-expressions the right type?

slide-50
SLIDE 50

sealed trait Value case class IntValue(n: Int) extends Expr case class BooleanValue(b: Boolean) extends Expr def eval(program: Expr): Either[Error, Value] = program match { case Lit(n) =? ??? case Lt(a, b) =? ??? case And(a, b) =? ??? }

Are sub-expressions the right type?

slide-51
SLIDE 51

sealed trait Value case class IntValue(n: Int) extends Expr case class BooleanValue(b: Boolean) extends Expr def eval(program: Expr): Either[Error, Value] = program match { case Lit(n) =? Right(IntValue(n)) case Lt(a, b) =? val x = evalAsInt(a) val y = evalAsInt(b) x.flatMap(a =? y.map(b =? a < b)) case And(a, b) =? val x = evalAsBool(a) val y = evalAsBool(b) x.flatMap(a =? y.map(b =? a &' b)) }

slide-52
SLIDE 52

Language mismatch Complex interpreter

slide-53
SLIDE 53

Can this be simplified?

slide-54
SLIDE 54

Typed DSLs

slide-55
SLIDE 55

sealed trait Expr case class Lit(value: Int) extends Expr case class Lt(a: Expr, b: Expr) extends Expr case class And(a: Expr, b: Expr) extends Expr

slide-56
SLIDE 56

sealed trait Expr[A] case class Lit[A](value: A) extends Expr[A] case class Lt(a: Expr[Int], b: Expr[Int]) extends Expr[Boolean] case class And(a: Expr[Boolean], b: Expr[Boolean]) extends Expr[Boolean]

slide-57
SLIDE 57

val validProgram: Expr[Boolean] = And(Lt(Lit(1), Lit(2)), Lt(Lit(3), Lit(4))) 


slide-58
SLIDE 58

val invalidProgram: Expr[Boolean] = Lt(And(Lit(1), Lit(2)), And(Lit(3), Lit(4))) /0 ^ expected Expr[Boolean], found Expr[Int]

slide-59
SLIDE 59

def eval[A](program: Expr[A]): A = program match { case Lit(v) =? v case Lt(a, b) =? eval(a) < eval(b) case And(a, b) =? eval(a) &' eval(b) }

slide-60
SLIDE 60

def evalAsync[A](program: Expr[A]): Future[A] = program match { case Lit(v) =? v case Lt(a, b) =? val x = evalAsync(a) val y = evalAsync(b) x.flatMap(a =? y.map(b =? a < b)) case And(a, b) =? val x = evalAsync(a) val y = evalAsync(b) x.flatMap(a =? y.map(b =? a &' b)) }

slide-61
SLIDE 61

def prettyPrint[A](program: Expr[A]): String = program match { case Lit(v) =? v.toString case Lt(a, b) =? s"${prettyPrint(a)} < ${prettyPrint(b)}" case And(a, b) =? s"${prettyPrint(a)} &' ${prettyPrint(b)}" }

slide-62
SLIDE 62

def simplify[A](program: Expr[A]): Expr[A] = program match { case Lit(n) =? Lit(n) case Lt(Lit(a), Lit(b)) =? Lit(a < b) case Lt(a, b) =? Lt(simplify(a), simplify(b)) case And(a, b) =? And(simplify(a), simplify(b)) }

slide-63
SLIDE 63

Deeper embedding Simpler interpreter

slide-64
SLIDE 64

Ordering

slide-65
SLIDE 65

def eval[A](program: Expr[A]): A = program match { case Lit(v) =? v case Lt(a, b) =? eval(a) < eval(b) case And(a, b) =? eval(a) &' eval(b) }

slide-66
SLIDE 66

Can we have
 explicit ordering?

slide-67
SLIDE 67

Yes, with monads!

slide-68
SLIDE 68

Monadic DSLs

slide-69
SLIDE 69

sealed trait Expr[A] case class Lit[A](value: A) extends Expr[A] case class Lt(a: Expr[Int], b: Expr[Int]) extends Expr[Boolean] case class And(a: Expr[Boolean], b: Expr[Boolean]) extends Expr[Boolean]

slide-70
SLIDE 70

sealed trait Expr[A] case class Lit[A](value: A) extends Expr[A] case class Lt(a: Expr[Int], b: Expr[Int]) extends Expr[Boolean] case class And(a: Expr[Boolean], b: Expr[Boolean]) extends Expr[Boolean] case class FlatMap[A, B]( a: Expr[A], f: A =? Expr[B]) extends Expr[B]

slide-71
SLIDE 71

sealed trait Expr[A] case class Lit[A](value: A) extends Expr[A] case class Lt(a: Int, b: Int) extends Expr[Boolean] case class And(a: Boolean, b: Boolean) extends Expr[Boolean] case class FlatMap[A, B]( a: Expr[A], f: A =? Expr[B]) extends Expr[B]

slide-72
SLIDE 72

sealed trait Expr[A] case class Pure[A](value: A) extends Expr[A] case class Lt(a: Int, b: Int) extends Expr[Boolean] case class And(a: Boolean, b: Boolean) extends Expr[Boolean] case class FlatMap[A, B]( a: Expr[A], f: A =? Expr[B]) extends Expr[B]

slide-73
SLIDE 73

val program: Expr[Boolean] = And(Lt(Pure(1), Pure(2)), Lt(Pure(3), Pure(4)))

slide-74
SLIDE 74

val program: Expr[Boolean] = FlatMap(Pure(1), (a: Int) =? FlatMap(Pure(2), (b: Int) =? FlatMap(Lt(a, b), (x: Boolean) =? FlatMap(Pure(3), (c: Int) =? FlatMap(Pure(4), (d: Int) =? FlatMap(Lt(c, d), (y: Boolean) =? FlatMap(And(x, y), (z: Boolean) =? Pure(z))))))))

slide-75
SLIDE 75

val program: Expr[Boolean] = for { a <. pure(1) b <. pure(2) x <. lt(a, b) c <. pure(3) d <. pure(4) y <. lt(c, d) z <. and(a, b) } yield z

slide-76
SLIDE 76

def eval[A](program: Expr[A]): A = program match { case Pure(v) =? v case Lt(a, b) =? a < b case And(a, b) =? a &' b case FlatMap(a, fn) =? eval(fn(eval(a)) }

slide-77
SLIDE 77

def evalAsync[A](program: Expr[A]): Future[A] = program match { case Pure(v) =? Future.successful(v) case Lt(a, b) =? Future.successful(a < b) case And(a, b) =? Future.successful(a &' b) case FlatMap(a, fn) =? evalAsync(a).flatMap(a =? evalAsync(fn(a)) }

slide-78
SLIDE 78

def prettyPrint[A](program: Expr[A]): String = program match { case Pure(v) =? v.toString case Lt(a, b) =? s"${prettyPrint(a)} < ${prettyPrint(b)}" case And(a, b) =? s"${prettyPrint(a)} &' ${prettyPrint(b)}" case FlatMap(a, fn) =? ??? }

slide-79
SLIDE 79

def simplify[A](program: Expr[A]): Expr[A] = program match { case Pure(v) =? ??? case Lt(a, b) =? ??? case And(a, b) =? ??? case FlatMap(a, fn) =? ??? }

slide-80
SLIDE 80

Generality Inspectability

slide-81
SLIDE 81

Do we have to 
 write FlatMap ourselves?

slide-82
SLIDE 82

Free monadic DSLs

slide-83
SLIDE 83

Abstract Pure/FlatMap

slide-84
SLIDE 84

sealed trait Expr[A] case class Pure[A](value: A) extends Expr[A] case class Lt(a: Int, b: Int) extends Expr[Boolean] case class And(a: Boolean, b: Boolean) extends Expr[Boolean] case class FlatMap[A, B]( a: Expr[A], f: A =? Expr[B]) extends Expr[B]

slide-85
SLIDE 85

sealed trait Expr[A] case class Lt(a: Int, b: Int) extends Expr[Boolean] case class And(a: Boolean, b: Boolean) extends Expr[Boolean] case class Pure[A](value: A) extends Expr[A] case class FlatMap[A, B]( a: Expr[A], f: A =? Expr[B]) extends Expr[B]

slide-86
SLIDE 86

sealed trait ExprAlg[A] case class Lt(a: Int, b: Int) extends ExprAlg[Boolean] case class And(a: Boolean, b: Boolean) extends ExprAlg[Boolean] case class Pure[A](value: A) extends Expr[A] case class FlatMap[A, B]( a: Expr[A], f: A =? Expr[B]) extends Expr[B]

slide-87
SLIDE 87

sealed trait ExprAlg[A] case class Lt(a: Int, b: Int) extends ExprAlg[Boolean] case class And(a: Boolean, b: Boolean) extends ExprAlg[Boolean] sealed trait ExprMonad[A] case class Pure[A](value: A) extends ExprMonad[A] case class FlatMap[A, B]( a: ExprMonad[A], f: A =? ExprMonad[B]) extends ExprMonad[B]

slide-88
SLIDE 88

sealed trait ExprAlg[A] case class Lt(a: Int, b: Int) extends ExprAlg[Boolean] case class And(a: Boolean, b: Boolean) extends ExprAlg[Boolean] sealed trait ExprMonad[A] case class Pure[A](value: A) extends ExprMonad[A] case class Suspend[A](value: ExprAlg[A]) extends ExprMonad[A] case class FlatMap[A, B]( a: ExprMonad[A], f: A =? ExprMonad[B]) extends ExprMonad[B]

slide-89
SLIDE 89

sealed trait ExprMonad[A] case class Pure[A](value: A) extends ExprMonad[A] case class Suspend[A](value: ExprAlg[A]) extends ExprMonad[A] case class FlatMap[A, B]( a: ExprMonad[A], f: A =? ExprMonad[B]) extends ExprMonad[B]

slide-90
SLIDE 90

sealed trait Free[F[_], A] case class Pure[F[_], A](value: A) extends Free[F, A] case class Suspend[F[_], A](value: F[A]) extends Free[F, A] case class FlatMap[F[_], A, B]( a: Free[F, A], f: A =? Free[F, B]) extends Free[F, B]

slide-91
SLIDE 91

sealed trait ExprAlg[A] case class Lt(a: Int, b: Int) extends ExprAlg[Boolean] case class And(a: Boolean, b: Boolean) extends ExprAlg[Boolean]

slide-92
SLIDE 92

val program: Expr[Boolean] = FlatMap(Pure(1), (a: Int) =? FlatMap(Pure(2), (b: Int) =? FlatMap(Suspend(Lt(a, b)), (x: Boolean) =? FlatMap(Pure(3), (c: Int) =? FlatMap(Pure(4), (d: Int) =? FlatMap(Suspend(Lt(c, d)), (y: Boolean) =? FlatMap(Suspend(And(x, y)), (z: Boolean) =? Pure(z))))))))

slide-93
SLIDE 93

val program: Expr[Boolean] = for { a <. pure(1) b <. pure(2) x <. suspend(lt(a, b)) c <. pure(3) d <. pure(4) y <. suspend(lt(c, d)) z <. suspend(and(x, y)) } yield z

slide-94
SLIDE 94

import cats.free.Free type Expr[A] = Free[ExprAlg, A]

slide-95
SLIDE 95

import cats.free.Free type Expr[A] = Free[ExprAlg, A] def lit[A](value: A): Expr[A] = Free.pure[ExprAlg, A](value) def lt(a: Int, b: Int): Expr[Boolean] = Free.liftF[ExprAlg, Boolean](Lt(a, b)) def and(a: Boolean, b: Boolean): Expr[Boolean] = Free.liftF[ExprAlg, Boolean](And(a, b)) def fail[A](msg, String): Expr[A] = Free.liftF[ExprAlg, A](Fail(msg))

slide-96
SLIDE 96

val program: Expr[Boolean] = for { a <. lit(1) b <. lit(2) x <. lt(a, b) c <. lit(3) d <. lit(4) y <. lt(c, d) z <. and(x, y) } yield z

slide-97
SLIDE 97

import cats.arrow.FunctionK

  • bject evalAsync extends FunctionK[ExprAlg, Future] {

def apply[A](expr: ExprAlg[A]): Future[A] = expr match { case Lt(a, b) =? Future.successful(a < b) case And(a, b) =? Future.successful(a &' b) } }

slide-98
SLIDE 98

val program: Expr[Boolean] = for { a <. lit(1) b <. lit(2) x <. lt(a, b) c <. lit(3) d <. lit(4) y <. lt(c, d) z <. and(x, y) } yield z program.foldMap(evalAsync) /0 res0: Future[Boolean] = Future(…)

slide-99
SLIDE 99

import cats.arrow.FunctionK import cats.Id

  • bject eval extends FunctionK[ExprAlg, Id] {

def apply[A](expr: ExprAlg[A]): A = expr match { case Lt(a, b) =? a < b case And(a, b) =? a &' b } }

slide-100
SLIDE 100

Free provides sequencing
 
 Algebra provides steps

slide-101
SLIDE 101

Combine DSLs

slide-102
SLIDE 102

import cats.data.EitherK import cats.free.Free type Alg[A] = EitherK[Alg1, Alg2, A] type Expr[A] = Free[Alg, A]

slide-103
SLIDE 103

Lots of boilerplate


(see Freestyle, hCp:/ /frees.io)

slide-104
SLIDE 104

Church encodings

slide-105
SLIDE 105

Encode programs 
 as Scala expressions

slide-106
SLIDE 106

Simple 
 Church encoding

slide-107
SLIDE 107

sealed trait Expr[A] case class Lit[A](value: A) extends Expr[A] case class Lt(a: Int, b: Int) extends Expr[Boolean] case class And(a: Boolean, b: Boolean) extends Expr[Boolean]

slide-108
SLIDE 108

trait ExprDsl { def lit[A](n: A): A def lt(a: Int, b: Int): Boolean def and(a: Boolean, b: Boolean): Boolean }

slide-109
SLIDE 109

def program(dsl: ExprDsl): Boolean = { import dsl._ and(lt(lit(1), lit(2)), lt(lit(3), lit(4))) }

slide-110
SLIDE 110
  • bject Interpreter extends ExprDsl {

def lit[A](n: A): A = n def lt(a: Int, b: Int): Boolean = a < b def and(a: Boolean, b: Boolean): Boolean = a &' b }

slide-111
SLIDE 111

def program(dsl: ExprDsl): Boolean = { import dsl._ and(lt(lit(1), lit(2)), lt(lit(3), lit(4))) } program(Interpreter) /0 res0: Boolean = true

slide-112
SLIDE 112

Can’t abstract over effects

slide-113
SLIDE 113

Tagless final encoding

slide-114
SLIDE 114

Tagless final encoding


(Finally tagless encoding?)

slide-115
SLIDE 115

trait ExprDsl { def lit[A](n: A): A def lt(a: Int, b: Int): Boolean def and(a: Boolean, b: Boolean): Boolean }

slide-116
SLIDE 116

trait ExprDsl[F[_]] { def lit[A](n: A): F[A] def lt(a: Int, b: Int): F[Boolean] def and(a: Boolean, b: Boolean): F[Boolean] }

slide-117
SLIDE 117
  • bject AsyncInterpreter extends ExprDsl[Future] {

def lit[A](n: A): Future[A] = Future.successful(n) def lt(a: Int, b: Int): Future[Boolean] = Future.successful(a < b) def and(a: Boolean, b: Boolean): Future[Boolean] = Future.successful(a &' b) }

slide-118
SLIDE 118

import cats.Id

  • bject Interpreter extends ExprDsl[Id] {

def lit[A](n: A): Id[A] = n def lt(a: Int, b: Int): Id[Boolean] = a < b def and(a: Boolean, b: Boolean): Id[Boolean] = a &' b }

slide-119
SLIDE 119

import cats.Monad import cats.syntax.functor._ import cats.syntax.flatMap._ def program[F[_]](dsl: ExprDsl[F]) (implicit monad: Monad): F[Boolean] = { import dsl._ for { a <. lit(1) b <. lit(2) x <. lt(a, b) c <. lit(3) d <. lit(4) y <. lt(c, d) z <. and(x, y) } yield z }

slide-120
SLIDE 120

import cats.Monad import cats.instances.future._ import cats.syntax.functor._ import cats.syntax.flatMap._ def program[F[_]](dsl: ExprDsl[F]) (implicit monad: Monad): F[Boolean] = { import dsl._ for { a <. lit(1) b <. lit(2) x <. lt(a, b) c <. lit(3) d <. lit(4) y <. lt(c, d) z <. and(x, y) } yield z } program(AsyncInterpreter) /0res0: Future[Boolean] = Future(Success(true))

slide-121
SLIDE 121

import cats.Monad import cats.syntax.functor._ import cats.syntax.flatMap._ def program[F[_]](dsl: ExprDsl[F]) (implicit monad: Monad): F[Boolean] = { import dsl._ for { a <. lit(1) b <. lit(2) x <. lt(a, b) c <. lit(3) d <. lit(4) y <. lt(c, d) z <. and(x, y) } yield z } program(Interpreter) res0: Id[Boolean] = true

slide-122
SLIDE 122

Combine DSLs

slide-123
SLIDE 123

def program[F[_], A](dsl1: Dsl1[F], dsl2: Dsl2[F]) (implicit monad: Monad[F]): A = { import dsl1._ import dsl2._ /0 ../ }

slide-124
SLIDE 124

Difficult to inspect

slide-125
SLIDE 125

Less boilerplate than Free

slide-126
SLIDE 126

Summary

slide-127
SLIDE 127

Interpreter Program Result

slide-128
SLIDE 128

Interpreter Program 2 Result 2 Program 1 Program 3 Result 1 Result 3

slide-129
SLIDE 129

Program

Interpreter 2 Interpreter 1 Interpreter 3

Result 1 Result 3 Result 2

slide-130
SLIDE 130

Model code as data


Model code as … code

Reifica?on Free Tagless final Church encoding

slide-131
SLIDE 131

Standalone


Completely custom


Embedded


Reuse host language features

slide-132
SLIDE 132

Constraints liberate, liberty constrains


hCps:/ /www.youtube.com/watch?v=GqmsQeSzMdw

Free


hCps:/ /underscore.io/blog/posts/
 2015/04/14/free-monads-are-simple.html

Free with mul?ple algebras


hCps:/ /underscore.io/blog/posts/
 2017/03/29/free-inject.html

Tagless final


hCps:/ /skillsmaCer.com/skillscasts/
 10007-free-vs-tagless-final-with-chris-birchall

slide-133
SLIDE 133

Slides, code samples, and notes (WIP)


hCps:/ /github.com/underscoreio/
 interpreters-and-you

slide-134
SLIDE 134

Dave Gurnell, @davegurnell Mark Mynsted, @mmynsted

Thank you

hCps:/ /github.com/underscoreio/
 interpreters-and-you