Evaluation ` a la Carte Non-Strict Evaluation via Compositional - - PowerPoint PPT Presentation

evaluation a la carte
SMART_READER_LITE
LIVE PREVIEW

Evaluation ` a la Carte Non-Strict Evaluation via Compositional - - PowerPoint PPT Presentation

Evaluation ` a la Carte Non-Strict Evaluation via Compositional Data Types Patrick Bahr University of Copenhagen, Department of Computer Science paba@diku.dk 23rd Nordic Workshop on Programming Theory, M alardalen University, V aster


slide-1
SLIDE 1

Evaluation ` a la Carte

Non-Strict Evaluation via Compositional Data Types Patrick Bahr

University of Copenhagen, Department of Computer Science paba@diku.dk

23rd Nordic Workshop on Programming Theory, M¨ alardalen University, V¨ aster˚ as, Sweden, October 26 - 28, 2011

slide-2
SLIDE 2

Outline

1

Compositional Data Types

2

Monadic Catamorphisms & Thunks

3

Conclusions

2

slide-3
SLIDE 3

Outline

1

Compositional Data Types

2

Monadic Catamorphisms & Thunks

3

Conclusions

3

slide-4
SLIDE 4

A Solution to the Expression Problem

Expression Problem [Phil Wadler] The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety.

4

slide-5
SLIDE 5

A Solution to the Expression Problem

Expression Problem [Phil Wadler] The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety. “Data Types ` a la Carte” by Wouter Swierstra (2008) A solution to the expression problem: Decoupling + Composition!

4

slide-6
SLIDE 6

A Solution to the Expression Problem

Expression Problem [Phil Wadler] The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety. “Data Types ` a la Carte” by Wouter Swierstra (2008) A solution to the expression problem: Decoupling + Composition! data types: decoupling of signature and term construction functions: decoupling of pattern matching and recursion

4

slide-7
SLIDE 7

A Solution to the Expression Problem

Expression Problem [Phil Wadler] The goal is to define a data type by cases, where one can add new cases to the data type and new functions over the data type, without recompiling existing code, and while retaining static type safety. “Data Types ` a la Carte” by Wouter Swierstra (2008) A solution to the expression problem: Decoupling + Composition! data types: decoupling of signature and term construction functions: decoupling of pattern matching and recursion signatures & functions defined on them can be composed

4

slide-8
SLIDE 8

Example: Evaluation Function

Example (A simple expression language) data Exp = Const Int | Pair Exp Exp | Mult Exp Exp | Fst Exp data Value = VConst Int | VPair Value Value

5

slide-9
SLIDE 9

Example: Evaluation Function

Example (A simple expression language) data Exp = Const Int | Pair Exp Exp | Mult Exp Exp | Fst Exp data Value = VConst Int | VPair Value Value eval :: Exp → Value eval (Const n) = VConst n eval (Pair x y) = VPair (eval x) (eval y) eval (Mult x y) = let VConst m = eval x VConst n = eval y in VConst (m ∗ n) eval (Fst p) = let VPair x y = eval p in x

5

slide-10
SLIDE 10

Decoupling Signature and Term Construction

Remove recursion from data type definition data Exp = Const Int | Pair Exp Exp | Mult Exp Exp | Fst Exp

6

slide-11
SLIDE 11

Decoupling Signature and Term Construction

Remove recursion from data type definition data Exp = Const Int | Pair Exp Exp | Mult Exp Exp | Fst Exp ⇓ data Sig e = Const Int | Pair e e | Mult e e | Fst e

6

slide-12
SLIDE 12

Decoupling Signature and Term Construction

Remove recursion from data type definition data Exp = Const Int | Pair Exp Exp | Mult Exp Exp | Fst Exp ⇓ data Sig e = Const Int | Pair e e | Mult e e | Fst e Recursion can be added separately data Term f = Term (f (Term f )) Term f is the initial f -algebra (a.k.a. term algebra over f )

6

slide-13
SLIDE 13

Decoupling Signature and Term Construction

Remove recursion from data type definition data Exp = Const Int | Pair Exp Exp | Mult Exp Exp | Fst Exp ⇓ data Sig e = Const Int | Pair e e | Mult e e | Fst e Recursion can be added separately data Term f = Term (f (Term f )) Term f is the initial f -algebra (a.k.a. term algebra over f ) Term Sig ∼ = Exp (modulo strictness)

6

slide-14
SLIDE 14

Combining Signatures

In order to extend expressions, we need a way to combine signatures. Direct sum of signatures data (f ⊕ g) e = Inl (f e) | Inr (g e) f ⊕ g is the sum of the signatures f and g

7

slide-15
SLIDE 15

Combining Signatures

In order to extend expressions, we need a way to combine signatures. Direct sum of signatures data (f ⊕ g) e = Inl (f e) | Inr (g e) f ⊕ g is the sum of the signatures f and g Example data Sig e = Const Int | Pair e e | Mult e e | Fst e

7

slide-16
SLIDE 16

Combining Signatures

In order to extend expressions, we need a way to combine signatures. Direct sum of signatures data (f ⊕ g) e = Inl (f e) | Inr (g e) f ⊕ g is the sum of the signatures f and g Example data Sig e = Const Int | Pair e e | Mult e e | Fst e

  • data Val e = Const Int

| Pair e e data Op e = Mult e e | Fst e

7

slide-17
SLIDE 17

Combining Signatures

In order to extend expressions, we need a way to combine signatures. Direct sum of signatures data (f ⊕ g) e = Inl (f e) | Inr (g e) f ⊕ g is the sum of the signatures f and g Example data Sig e = Const Int | Pair e e | Mult e e | Fst e

  • data Val e = Const Int

| Pair e e data Op e = Mult e e | Fst e Val ⊕ Op ∼ = Sig

7

slide-18
SLIDE 18

Combining Signatures

In order to extend expressions, we need a way to combine signatures. Direct sum of signatures data (f ⊕ g) e = Inl (f e) | Inr (g e) f ⊕ g is the sum of the signatures f and g Example type Sig = Val ⊕ Op data Val e = Const Int | Pair e e data Op e = Mult e e | Fst e

7

slide-19
SLIDE 19

Combining Signatures

In order to extend expressions, we need a way to combine signatures. Direct sum of signatures data (f ⊕ g) e = Inl (f e) | Inr (g e) f ⊕ g is the sum of the signatures f and g Example type Sig = Val ⊕ Op data Val e = Const Int | Pair e e data Op e = Mult e e | Fst e Term Sig ∼ = Exp Term Val ∼ = Value

7

slide-20
SLIDE 20

Subsignatures

Subsignature type class class f ≺ g where ...

8

slide-21
SLIDE 21

Subsignatures

Subsignature type class class f ≺ g where ... f ≺ g iff g = g1 ⊕ g2 ⊕ ... ⊕ gn and f = gi, 0 < i ≤ n

8

slide-22
SLIDE 22

Subsignatures

Subsignature type class class f ≺ g where ... For example: Val ≺ Val ⊕ Op

  • Sig

f ≺ g iff g = g1 ⊕ g2 ⊕ ... ⊕ gn and f = gi, 0 < i ≤ n

8

slide-23
SLIDE 23

Subsignatures

Subsignature type class class f ≺ g where ... For example: Val ≺ Val ⊕ Op

  • Sig

f ≺ g iff g = g1 ⊕ g2 ⊕ ... ⊕ gn and f = gi, 0 < i ≤ n Injection and projection functions inject :: (g ≺ f ) ⇒ g (Term f ) → Term f project :: (g ≺ f ) ⇒ Term f → Maybe (g (Term f ))

8

slide-24
SLIDE 24

Separating Function Definition from Recursion

Compositional function definitions as algebras In the same way as we defined the types: define functions on the signatures (non-recursive): f a → a combine functions using type classes apply the resulting function recursively on the term: Term f → a

9

slide-25
SLIDE 25

Separating Function Definition from Recursion

Compositional function definitions as algebras In the same way as we defined the types: define functions on the signatures (non-recursive): f a → a combine functions using type classes apply the resulting function recursively on the term: Term f → a Algebras class Eval f where evalAlg :: f (Term Val) → Term Val

9

slide-26
SLIDE 26

Separating Function Definition from Recursion

Compositional function definitions as algebras In the same way as we defined the types: define functions on the signatures (non-recursive): f a → a combine functions using type classes apply the resulting function recursively on the term: Term f → a Algebras class Eval f where evalAlg :: f (Term Val) → Term Val Applying a function recursively to a term cata :: Functor f ⇒ (f a → a) → Term f → a cata f (Term t) = f (fmap (cata f ) t)

9

slide-27
SLIDE 27

Defining Algebras

On the singleton signatures instance Eval Val where evalAlg = inject

10

slide-28
SLIDE 28

Defining Algebras

On the singleton signatures instance Eval Val where evalAlg = inject Val (Term Val) → Term Val

10

slide-29
SLIDE 29

Defining Algebras

On the singleton signatures instance Eval Val where evalAlg = inject instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x

10

slide-30
SLIDE 30

Defining Algebras

On the singleton signatures instance Eval Val where evalAlg = inject instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x Forming the catamorphism eval :: Term Sig → Term Val eval = cata evalAlg

10

slide-31
SLIDE 31

Outline

1

Compositional Data Types

2

Monadic Catamorphisms & Thunks

3

Conclusions

11

slide-32
SLIDE 32

Monadic Catamorphisms

Fear the bottoms!

instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x

12

slide-33
SLIDE 33

Monadic Catamorphisms

Fear the bottoms!

instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x The case distinction is incomplete

12

slide-34
SLIDE 34

Monadic Catamorphisms

Fear the bottoms!

instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x

Monadic Algebra

instance Eval Op where evalAlg (Mult x y) = do Const m ← project x Const n ← project y return (inject (Const (m ∗ n))) evalAlg (Fst p) = do Pair x y ← project p return x

12

slide-35
SLIDE 35

Monadic Catamorphisms

Fear the bottoms!

instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x

Monadic Algebra

instance Eval Op where evalAlg (Mult x y) = do Const m ← project x Const n ← project y return (inject (Const (m ∗ n))) evalAlg (Fst p) = do Pair x y ← project p return x Op (Term Val) → Maybe (Term Val)

12

slide-36
SLIDE 36

Monadic Catamorphisms

Fear the bottoms!

instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x

Monadic Algebra

instance Eval Op where evalAlg (Mult x y) = do Const m ← project x Const n ← project y return (inject (Const (m ∗ n))) evalAlg (Fst p) = do Pair x y ← project p return x both x and y are evaluated

12

slide-37
SLIDE 37

Monadic Catamorphisms

Fear the bottoms!

instance Eval Op where evalAlg (Mult x y) = let Just (Const m) = project x Just (Const n) = project y in inject (Const (m ∗ n)) evalAlg (Fst p) = let Just (Pair x y) = project p in x

Monadic Algebra

instance Eval Op where evalAlg (Mult x y) = do Const m ← project x Const n ← project y return (inject (Const (m ∗ n))) evalAlg (Fst p) = do Pair x y ← project p return x both x and y are evaluated Stricter than non-monadic evaluation!

12

slide-38
SLIDE 38

The Type of the Monadic Evaluation Function eval :: Term Sig → m (Term Val)

13

slide-39
SLIDE 39

The Type of the Monadic Evaluation Function m (Term Val)

13

slide-40
SLIDE 40

The Type of the Monadic Evaluation Function m (Term Val)

13

slide-41
SLIDE 41

The Type of the Monadic Evaluation Function Term (m ⊕Val)

13

slide-42
SLIDE 42

Creating and Evaluating Thunks

Creating a thunk thunk :: m (Term (m ⊕ f )) → Term (m ⊕ f ) thunk = inject

14

slide-43
SLIDE 43

Creating and Evaluating Thunks

Creating a thunk thunk :: m (Term (m ⊕ f )) → Term (m ⊕ f ) thunk = inject Evaluation to weak head normal form whnf :: Monad m ⇒ Term (m ⊕ f ) → m (f (Term (m ⊕ f )))

14

slide-44
SLIDE 44

Creating and Evaluating Thunks

Creating a thunk thunk :: m (Term (m ⊕ f )) → Term (m ⊕ f ) thunk = inject Evaluation to weak head normal form whnf :: Monad m ⇒ Term (m ⊕ f ) → m (f (Term (m ⊕ f ))) whnf (Term (Inl m)) = m > > = whnf whnf (Term (Inr t)) = return t

14

slide-45
SLIDE 45

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val))

15

slide-46
SLIDE 46

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val))

15

slide-47
SLIDE 47

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val)) evalAlg :: f (Term Val) → Maybe (Term Val)

15

slide-48
SLIDE 48

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val)) instance EvalT Val where evalAlgT = inject

15

slide-49
SLIDE 49

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val)) instance EvalT Val where evalAlgT = inject Evaluating operators instance EvalT Op where evalAlgT (Mult x y) = thunk $ do Const i ← whnf x Const j ← whnf y return (inject (Const (i ∗ j))) evalAlgT (Fst v) = thunk $ do Pair x y ← whnf v return x

15

slide-50
SLIDE 50

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val)) instance EvalT Val where evalAlgT = inject Evaluating operators instance EvalT Op where evalAlgT (Mult x y) = thunk $ do Const i ← whnf x Const j ← whnf y return (inject (Const (i ∗ j))) evalAlgT (Fst v) = thunk $ do Pair x y ← whnf v return x

15

slide-51
SLIDE 51

Evaluation via Thunks

Algebra declaration & trivial instance class EvalT f where evalAlgT :: f (Term (Maybe ⊕ Val)) → Term (Maybe ⊕ Val)) instance EvalT Val where evalAlgT = inject Evaluating operators instance EvalT Op where evalAlgT (Mult x y) = thunk $ do Const i ← whnf x Const j ← whnf y return (inject (Const (i ∗ j))) evalAlgT (Fst v) = thunk $ do Pair x y ← whnf v return x

15

slide-52
SLIDE 52

Obtaining the Evaluation Function

Forming the catamorphism evalT :: Term Sig → Term (Maybe ⊕ Val) evalT = cata evalAlgT

16

slide-53
SLIDE 53

Obtaining the Evaluation Function

Forming the catamorphism evalT :: Term Sig → Term (Maybe ⊕ Val) evalT = cata evalAlgT Evaluating to normal form nf :: (Monad m, Traversable f ) ⇒ Term (m ⊕ f ) → m (Term f ) nf = liftM Term . mapM nf < = < whnf

16

slide-54
SLIDE 54

Obtaining the Evaluation Function

Forming the catamorphism evalT :: Term Sig → Term (Maybe ⊕ Val) evalT = cata evalAlgT Evaluating to normal form nf :: (Monad m, Traversable f ) ⇒ Term (m ⊕ f ) → m (Term f ) nf = liftM Term . mapM nf < = < whnf The evaluation function eval :: Term Sig → Maybe (Term Value) eval = nf . evalT

16

slide-55
SLIDE 55

Adding Strictness

Value constructors are non-strict instance EvalT Val where evalAlgT = inject

17

slide-56
SLIDE 56

Adding Strictness

Value constructors are non-strict instance EvalT Val where evalAlgT = inject Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf )

17

slide-57
SLIDE 57

Adding Strictness

Value constructors are non-strict instance EvalT Val where evalAlgT = inject Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf )

17

slide-58
SLIDE 58

Adding Strictness

Making value constructors strict instance EvalT Val where evalAlgT = strict Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf )

17

slide-59
SLIDE 59

Adding Strictness

Making value constructors strict instance EvalT Val where evalAlgT = strictAt spec where spec (Pair a b) = [b] spec = [ ] Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf )

17

slide-60
SLIDE 60

Adding Strictness

Making value constructors strict instance EvalT Val where evalAlgT = strictAt spec spec can be derived from Haskell strictness annotations where spec (Pair a b) = [b] spec = [ ] Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf )

17

slide-61
SLIDE 61

Adding Strictness

Making value constructors strict instance EvalT Val where evalAlgT = strictAt spec spec can be derived from Haskell strictness annotations where spec (Pair a b) = [b] spec = [ ] Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf ) Strictness annotations data Val a = Const Int | Pair a a

17

slide-62
SLIDE 62

Adding Strictness

Making value constructors strict instance EvalT Val where evalAlgT = strictAt spec spec can be derived from Haskell strictness annotations where spec (Pair a b) = [b] spec = [ ] Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf ) Strictness annotations data Val a = Const Int | Pair a ! a

17

slide-63
SLIDE 63

Adding Strictness

Making value constructors strict instance EvalT Val where evalAlgT = haskellStrict Making constructors strict strict :: (f ≺ g, Traversable f , Monad m) ⇒ f (Term (m ⊕ g)) → Term (m ⊕ g) strict = thunk . liftM inject . mapM (liftM inject . whnf ) Strictness annotations data Val a = Const Int | Pair a ! a

17

slide-64
SLIDE 64

Outline

1

Compositional Data Types

2

Monadic Catamorphisms & Thunks

3

Conclusions

18

slide-65
SLIDE 65

The Last Slide

What have we gained? Monadic computations with the same strictness as pure computations!

19

slide-66
SLIDE 66

The Last Slide

What have we gained? Monadic computations with the same strictness as pure computations! Other settings (parametric) higher-order abstract syntax mutually recursive data types

19

slide-67
SLIDE 67

The Last Slide

What have we gained? Monadic computations with the same strictness as pure computations! Other settings (parametric) higher-order abstract syntax mutually recursive data types Easy to use we use it ourselves for implementing DSLs

19

slide-68
SLIDE 68

The Last Slide

What have we gained? Monadic computations with the same strictness as pure computations! Other settings (parametric) higher-order abstract syntax mutually recursive data types Easy to use we use it ourselves for implementing DSLs

try it: cabal install compdata

19