Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Checked complexity with typed simplicity

Checked complexity with typed simplicity

Among the most important properties of software is 'modularity', the notion that you build complex modules from simpler ones. It is common practice to adhere to this concept in the context of logical components, such as separating an application into input, transformation, and output. Once we drill down into lower level details however, it can get a bit finicky to enforce the same kind of modularity. In this talk we will explore how we can build complex programs from simple building blocks regardless of the level we are working at, be it functions, modules, or (embedded) programs. Particularly, we will see how an expressive type system can be leveraged to keep our modularity in check as we build more and more complex modules. Examples will be given in Scala but techniques discussed are generally language agnostic.

Adelbert Chang

March 04, 2016
Tweet

More Decks by Adelbert Chang

Other Decks in Programming

Transcript

  1. When it comes to controlling the complexity of developing and,

    more importantly, maintaining a large system, the only game in town is modularity. "Modules Matter Most" Robert Harper 2 / 23
  2. A type system is a syntactic method for enforcing levels

    of abstraction in programs. "Types and Programming Languages" Benjamin C. Pierce 4 / 23
  3. These slides were compiled with Scala 2.11.7, Cats 0.4.1, and

    Kind-projector 0.7.1 using tut 0.4.2. 5 / 23
  4. Functions as values d e f d o u b

    l e I n t s ( i n t s : L i s t [ I n t ] ) : L i s t [ I n t ] = i n t s m a t c h { c a s e N i l = > N i l c a s e h : : t = > ( h * 2 ) : : d o u b l e I n t s ( t ) } 6 / 23
  5. Functions as values d e f d o u b

    l e I n t s ( i n t s : L i s t [ I n t ] ) : L i s t [ I n t ] = i n t s m a t c h { c a s e N i l = > N i l c a s e h : : t = > ( h * 2 ) : : d o u b l e I n t s ( t ) } d e f a d d 5 0 ( i n t s : L i s t [ I n t ] ) : L i s t [ I n t ] = i n t s m a t c h { c a s e N i l = > N i l c a s e h : : t = > ( h + 5 0 ) : : a d d 5 0 ( t ) } 6 / 23
  6. Functions as values d e f d o u b

    l e I n t s ( i n t s : L i s t [ I n t ] ) : L i s t [ I n t ] = i n t s m a t c h { c a s e N i l = > N i l c a s e h : : t = > ( h * 2 ) : : d o u b l e I n t s ( t ) } d e f a d d 5 0 ( i n t s : L i s t [ I n t ] ) : L i s t [ I n t ] = i n t s m a t c h { c a s e N i l = > N i l c a s e h : : t = > ( h + 5 0 ) : : a d d 5 0 ( t ) } d e f m a p I n t s ( i n t s : L i s t [ I n t ] ) ( f : I n t = > I n t ) : L i s t [ I n t ] = i n t s m a t c h { c a s e N i l = > N i l c a s e h : : t = > f ( h ) : : m a p I n t s ( t ) ( f ) } 6 / 23
  7. Type parameters d e f l i s t S

    t r i n g C o n c a t ( l e f t : L i s t [ S t r i n g ] , r i g h t : L i s t [ S t r i n g ] ) : L i s t [ S t r i n g ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t S t r i n g C o n c a t ( t , r i g h t ) } 7 / 23
  8. Type parameters d e f l i s t I

    n t C o n c a t ( l e f t : L i s t [ I n t ] , r i g h t : L i s t [ I n t ] ) : L i s t [ I n t ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t I n t C o n c a t ( t , r i g h t ) } d e f l i s t S t r i n g C o n c a t ( l e f t : L i s t [ S t r i n g ] , r i g h t : L i s t [ S t r i n g ] ) : L i s t [ S t r i n g ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t S t r i n g C o n c a t ( t , r i g h t ) } 7 / 23
  9. Type parameters d e f l i s t I

    n t C o n c a t ( l e f t : L i s t [ I n t ] , r i g h t : L i s t [ I n t ] ) : L i s t [ I n t ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t I n t C o n c a t ( t , r i g h t ) } Abstract out irrelevant information d e f l i s t S t r i n g C o n c a t ( l e f t : L i s t [ S t r i n g ] , r i g h t : L i s t [ S t r i n g ] ) : L i s t [ S t r i n g ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t S t r i n g C o n c a t ( t , r i g h t ) } 7 / 23
  10. Type parameters d e f l i s t I

    n t C o n c a t ( l e f t : L i s t [ I n t ] , r i g h t : L i s t [ I n t ] ) : L i s t [ I n t ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t I n t C o n c a t ( t , r i g h t ) } Abstract out irrelevant information d e f c o n c a t [ A ] ( l e f t : L i s t [ A ] , r i g h t : L i s t [ A ] ) : L i s t [ A ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : c o n c a t ( t , r i g h t ) } d e f l i s t S t r i n g C o n c a t ( l e f t : L i s t [ S t r i n g ] , r i g h t : L i s t [ S t r i n g ] ) : L i s t [ S t r i n g ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t S t r i n g C o n c a t ( t , r i g h t ) } 7 / 23
  11. Type parameters d e f l i s t I

    n t C o n c a t ( l e f t : L i s t [ I n t ] , r i g h t : L i s t [ I n t ] ) : L i s t [ I n t ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t I n t C o n c a t ( t , r i g h t ) } Abstract out irrelevant information d e f c o n c a t [ A ] ( l e f t : L i s t [ A ] , r i g h t : L i s t [ A ] ) : L i s t [ A ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : c o n c a t ( t , r i g h t ) } c o n c a t ( L i s t ( 1 , 2 ) , L i s t ( 3 , 4 , 5 ) ) c o n c a t ( L i s t ( " h e l l o " , " " ) , L i s t ( " w o r l d " ) ) c o n c a t ( L i s t ( ' a ' , ' b ' ) , L i s t ( ' c ' ) ) d e f l i s t S t r i n g C o n c a t ( l e f t : L i s t [ S t r i n g ] , r i g h t : L i s t [ S t r i n g ] ) : L i s t [ S t r i n g ] = l e f t m a t c h { c a s e N i l = > r i g h t c a s e h : : t = > h : : l i s t S t r i n g C o n c a t ( t , r i g h t ) } 7 / 23
  12. Functions as values + type parameters d e f f

    o l d R i g h t [ A , B ] ( a s : L i s t [ A ] , b : B ) ( f : ( A , B ) = > B ) : B = a s m a t c h { c a s e N i l = > b c a s e h : : t = > f ( h , f o l d R i g h t ( t , b ) ( f ) ) } 8 / 23
  13. Functions as values + type parameters d e f f

    o l d R i g h t [ A , B ] ( a s : L i s t [ A ] , b : B ) ( f : ( A , B ) = > B ) : B = a s m a t c h { c a s e N i l = > b c a s e h : : t = > f ( h , f o l d R i g h t ( t , b ) ( f ) ) } d e f s i z e [ A ] ( a s : L i s t [ A ] ) : I n t = f o l d R i g h t ( a s , 0 ) ( ( _ , s z ) = > s z + 1 ) d e f m a p [ A , B ] ( a s : L i s t [ A ] ) ( f : A = > B ) : L i s t [ B ] = f o l d R i g h t ( a s , L i s t . e m p t y [ B ] ) ( ( a , b s ) = > f ( a ) : : b s ) d e f c o n c a t [ A ] ( l e f t : L i s t [ A ] , r i g h t : L i s t [ A ] ) : L i s t [ A ] = f o l d R i g h t ( l e f t , r i g h t ) ( _ : : _ ) d e f f l a t t e n [ A ] ( a a s : L i s t [ L i s t [ A ] ] ) : L i s t [ A ] = a a s m a t c h { c a s e N i l = > N i l c a s e a s : : t = > c o n c a t ( a s , f l a t t e n ( t ) ) } d e f f l a t M a p [ A , B ] ( a s : L i s t [ A ] ) ( f : A = > L i s t [ B ] ) : L i s t [ B ] = f l a t t e n ( m a p ( a s ) ( f ) ) 8 / 23
  14. Type parameters, universal quantification For all (∀) A. Given a

    term of type A, I can produce a term of type A t r a i t F o r A l l { d e f a p p l y [ A ] ( a : A ) : A = a } 9 / 23
  15. Type parameters, universal quantification For all (∀) A. Given a

    term of type A, I can produce a term of type A t r a i t F o r A l l { d e f a p p l y [ A ] ( a : A ) : A = a } You may choose any A d e f f o r A l l I n t ( f : F o r A l l ) : I n t = > I n t = i = > f ( i ) 9 / 23
  16. Type members, existential quantification There exists (∃) an A such

    that given a term of type A, I can produce a term of type A t r a i t T h e r e E x i s t s { t y p e A d e f a p p l y ( a : A ) : A } 10 / 23
  17. Type members, existential quantification There exists (∃) an A such

    that given a term of type A, I can produce a term of type A t r a i t T h e r e E x i s t s { t y p e A d e f a p p l y ( a : A ) : A } I choose an A d e f t h e r e E x i s t s I n t ( e : T h e r e E x i s t s ) : I n t = > I n t = i = > e ( i ) / / < c o n s o l e > : 1 3 : e r r o r : t y p e m i s m a t c h ; / / f o u n d : i . t y p e ( w i t h u n d e r l y i n g t y p e I n t ) / / r e q u i r e d : e . A / / i = > e ( i ) / / ^ 10 / 23
  18. Type Members vs. Type Parameters (Hi Jon!) Type parameters =

    universal quantification = abstraction (Abstract) Type members = existential quantification = information hiding 11 / 23
  19. Type Members vs. Type Parameters: Example / / U n

    i v e r s a l l y q u a n t i f i e d A - k n o w n t o y o u t r a i t S t a c k [ A ] { / / E x i s t e n t i a l l y q u a n t i f i e d R e p r - k n o w n t o m e t y p e R e p r d e f e m p t y : R e p r d e f p u s h ( a : A , r : R e p r ) : R e p r d e f p o p ( r : R e p r ) : O p t i o n [ ( A , R e p r ) ] } 12 / 23
  20. Type Members vs. Type Parameters: Example / / U n

    i v e r s a l l y q u a n t i f i e d A - k n o w n t o y o u t r a i t S t a c k [ A ] { / / E x i s t e n t i a l l y q u a n t i f i e d R e p r - k n o w n t o m e t y p e R e p r d e f e m p t y : R e p r d e f p u s h ( a : A , r : R e p r ) : R e p r d e f p o p ( r : R e p r ) : O p t i o n [ ( A , R e p r ) ] } d e f p u s h 1 2 3 ( s t a c k : S t a c k [ I n t ] ) : s t a c k . R e p r = { i m p o r t s t a c k . _ p u s h ( 3 , p u s h ( 2 , p u s h ( 1 , e m p t y ) ) ) } 12 / 23
  21. Type Members vs. Type Parameters: Example / / U n

    i v e r s a l l y q u a n t i f i e d A - k n o w n t o y o u t r a i t S t a c k [ A ] { / / E x i s t e n t i a l l y q u a n t i f i e d R e p r - k n o w n t o m e t y p e R e p r d e f e m p t y : R e p r d e f p u s h ( a : A , r : R e p r ) : R e p r d e f p o p ( r : R e p r ) : O p t i o n [ ( A , R e p r ) ] } d e f p u s h 1 2 3 ( s t a c k : S t a c k [ I n t ] ) : s t a c k . R e p r = { i m p o r t s t a c k . _ p u s h ( 3 , p u s h ( 2 , p u s h ( 1 , e m p t y ) ) ) } / / I b e t t h e S t a c k i s a L i s t d e f p u s h 1 2 3 L i s t ( s t a c k : S t a c k [ I n t ] ) = s t a c k . p u s h ( 1 , L i s t ( 2 , 3 , 4 ) ) / / < c o n s o l e > : 1 4 : e r r o r : t y p e m i s m a t c h ; / / f o u n d : L i s t [ I n t ] / / r e q u i r e d : s t a c k . R e p r / / s t a c k . p u s h ( 1 , L i s t ( 2 , 3 , 4 ) ) / / ^ 12 / 23
  22. Kinds The "type" of types Types are to Values as

    Kinds are to Types * Int Char List[Int] Either[String, Int] 13 / 23
  23. Kinds The "type" of types Types are to Values as

    Kinds are to Types * Int Char List[Int] Either[String, Int] * - > * List Vector Future 13 / 23
  24. Kinds The "type" of types Types are to Values as

    Kinds are to Types * Int Char List[Int] Either[String, Int] * - > * List Vector Future ( * , * ) - > * Either Tuple2 13 / 23
  25. Higher-kinded types Types that abstract over type constructors "Generics of

    a Higher Kind" Adrian Moors, Frank Piessens, Martin Odersky 14 / 23
  26. Higher-kinded types Types that abstract over type constructors "Generics of

    a Higher Kind" Adrian Moors, Frank Piessens, Martin Odersky / / ( * - > * ) - > * t r a i t F u n c t o r [ F [ _ ] ] { d e f m a p [ A , B ] ( f a : F [ A ] ) ( f : A = > B ) : F [ B ] } t r a i t A p p l i c a t i v e [ F [ _ ] ] e x t e n d s F u n c t o r [ F ] { d e f m a p 2 [ A , B , C ] ( f a : F [ A ] , f b : F [ B ] ) ( f : ( A , B ) = > C ) : F [ C ] d e f p u r e [ A ] ( a : A ) : F [ A ] d e f m a p [ A , B ] ( f a : F [ A ] ) ( f : A = > B ) : F [ B ] = m a p 2 ( f a , p u r e ( ( ) ) ) ( ( a , _ ) = > f ( a ) ) } 14 / 23
  27. Higher-kinded types Types that abstract over type constructors "Generics of

    a Higher Kind" Adrian Moors, Frank Piessens, Martin Odersky / / ( * - > * ) - > * t r a i t F u n c t o r [ F [ _ ] ] { d e f m a p [ A , B ] ( f a : F [ A ] ) ( f : A = > B ) : F [ B ] } t r a i t A p p l i c a t i v e [ F [ _ ] ] e x t e n d s F u n c t o r [ F ] { d e f m a p 2 [ A , B , C ] ( f a : F [ A ] , f b : F [ B ] ) ( f : ( A , B ) = > C ) : F [ C ] d e f p u r e [ A ] ( a : A ) : F [ A ] d e f m a p [ A , B ] ( f a : F [ A ] ) ( f : A = > B ) : F [ B ] = m a p 2 ( f a , p u r e ( ( ) ) ) ( ( a , _ ) = > f ( a ) ) } v a l l i s t F u n c t o r : F u n c t o r [ L i s t ] = n e w F u n c t o r [ L i s t ] { d e f m a p [ A , B ] ( f a : L i s t [ A ] ) ( f : A = > B ) : L i s t [ B ] = f a m a t c h { c a s e N i l = > N i l c a s e h : : t = > f ( h ) : : m a p ( t ) ( f ) } } 14 / 23
  28. i m p o r t c a t s

    . A p p l i c a t i v e d e f t r a v e r s e L i s t [ G [ _ ] , A , B ] ( a s : L i s t [ A ] ) ( f : A = > G [ B ] ) ( i m p l i c i t G : A p p l i c a t i v e [ G ] ) : G [ L i s t [ B ] ] = a s . f o l d R i g h t ( G . p u r e ( L i s t . e m p t y [ B ] ) ) { ( a , b s ) = > G . m a p 2 ( f ( a ) , b s ) ( ( h , t ) = > h : : t ) } 15 / 23
  29. i m p o r t c a t s

    . A p p l i c a t i v e d e f t r a v e r s e L i s t [ G [ _ ] , A , B ] ( a s : L i s t [ A ] ) ( f : A = > G [ B ] ) ( i m p l i c i t G : A p p l i c a t i v e [ G ] ) : G [ L i s t [ B ] ] = a s . f o l d R i g h t ( G . p u r e ( L i s t . e m p t y [ B ] ) ) { ( a , b s ) = > G . m a p 2 ( f ( a ) , b s ) ( ( h , t ) = > h : : t ) } i m p o r t c a t s . i m p l i c i t s . _ i m p o r t s c a l a . c o n c u r r e n t . F u t u r e i m p o r t s c a l a . c o n c u r r e n t . E x e c u t i o n C o n t e x t . I m p l i c i t s . g l o b a l d e f p a r s e I n t O p t i o n ( s : S t r i n g ) : O p t i o n [ I n t ] = i f ( s . m a t c h e s ( " - ? [ 0 - 9 ] + " ) ) S o m e ( s . t o I n t ) e l s e N o n e t r a v e r s e L i s t ( L i s t ( " 1 " , " 2 " , " 3 " ) ) ( p a r s e I n t O p t i o n ) / / r e s 2 : O p t i o n [ L i s t [ I n t ] ] = S o m e ( L i s t ( 1 , 2 , 3 ) ) t r a v e r s e L i s t ( L i s t ( " h e l l o " , " 1 " , " w o r l d " ) ) ( p a r s e I n t O p t i o n ) / / r e s 3 : O p t i o n [ L i s t [ I n t ] ] = N o n e 15 / 23
  30. i m p o r t c a t s

    . A p p l i c a t i v e d e f t r a v e r s e L i s t [ G [ _ ] , A , B ] ( a s : L i s t [ A ] ) ( f : A = > G [ B ] ) ( i m p l i c i t G : A p p l i c a t i v e [ G ] ) : G [ L i s t [ B ] ] = a s . f o l d R i g h t ( G . p u r e ( L i s t . e m p t y [ B ] ) ) { ( a , b s ) = > G . m a p 2 ( f ( a ) , b s ) ( ( h , t ) = > h : : t ) } i m p o r t c a t s . i m p l i c i t s . _ i m p o r t s c a l a . c o n c u r r e n t . F u t u r e i m p o r t s c a l a . c o n c u r r e n t . E x e c u t i o n C o n t e x t . I m p l i c i t s . g l o b a l d e f p a r s e I n t O p t i o n ( s : S t r i n g ) : O p t i o n [ I n t ] = i f ( s . m a t c h e s ( " - ? [ 0 - 9 ] + " ) ) S o m e ( s . t o I n t ) e l s e N o n e t r a v e r s e L i s t ( L i s t ( " 1 " , " 2 " , " 3 " ) ) ( p a r s e I n t O p t i o n ) / / r e s 2 : O p t i o n [ L i s t [ I n t ] ] = S o m e ( L i s t ( 1 , 2 , 3 ) ) t r a v e r s e L i s t ( L i s t ( " h e l l o " , " 1 " , " w o r l d " ) ) ( p a r s e I n t O p t i o n ) / / r e s 3 : O p t i o n [ L i s t [ I n t ] ] = N o n e t r a v e r s e L i s t ( L i s t ( " h e l l o " , " w o r l d " ) ) ( s = > F u t u r e ( s + + s ) ) / / r e s 4 : s c a l a . c o n c u r r e n t . F u t u r e [ L i s t [ S t r i n g ] ] = s c a l a . c o n c u r r e n t . i m p l . P r o m i s e $ D e f a u l t P r o m 15 / 23
  31. i m p o r t c a t s

    . A p p l i c a t i v e d e f t r a v e r s e L i s t [ G [ _ ] , A , B ] ( a s : L i s t [ A ] ) ( f : A = > G [ B ] ) ( i m p l i c i t G : A p p l i c a t i v e [ G ] ) : G [ L i s t [ B ] ] = a s . f o l d R i g h t ( G . p u r e ( L i s t . e m p t y [ B ] ) ) { ( a , b s ) = > G . m a p 2 ( f ( a ) , b s ) ( ( h , t ) = > h : : t ) } i m p o r t c a t s . i m p l i c i t s . _ i m p o r t s c a l a . c o n c u r r e n t . F u t u r e i m p o r t s c a l a . c o n c u r r e n t . E x e c u t i o n C o n t e x t . I m p l i c i t s . g l o b a l d e f p a r s e I n t O p t i o n ( s : S t r i n g ) : O p t i o n [ I n t ] = i f ( s . m a t c h e s ( " - ? [ 0 - 9 ] + " ) ) S o m e ( s . t o I n t ) e l s e N o n e t r a v e r s e L i s t ( L i s t ( " 1 " , " 2 " , " 3 " ) ) ( p a r s e I n t O p t i o n ) / / r e s 2 : O p t i o n [ L i s t [ I n t ] ] = S o m e ( L i s t ( 1 , 2 , 3 ) ) t r a v e r s e L i s t ( L i s t ( " h e l l o " , " 1 " , " w o r l d " ) ) ( p a r s e I n t O p t i o n ) / / r e s 3 : O p t i o n [ L i s t [ I n t ] ] = N o n e t r a v e r s e L i s t ( L i s t ( " h e l l o " , " w o r l d " ) ) ( s = > F u t u r e ( s + + s ) ) / / r e s 4 : s c a l a . c o n c u r r e n t . F u t u r e [ L i s t [ S t r i n g ] ] = s c a l a . c o n c u r r e n t . i m p l . P r o m i s e $ D e f a u l t P r o m t r a v e r s e L i s t ( L i s t ( ' a ' , ' b ' , ' c ' ) ) ( c = > L i s t ( c , c , c ) ) / / r e s 5 : L i s t [ L i s t [ C h a r ] ] = L i s t ( L i s t ( a , b , c ) , L i s t ( a , b , c ) , L i s t ( a , b , c ) , L i s t ( a , b , c 15 / 23
  32. Embedded DSLs Build an AST of your DSL Separate structure

    from interpretation A program inside your program 17 / 23
  33. Embedded DSLs Build an AST of your DSL Separate structure

    from interpretation A program inside your program Pass AST around in your program, avoiding interpretation until the end 17 / 23
  34. Embedded DSLs Build an AST of your DSL Separate structure

    from interpretation A program inside your program Pass AST around in your program, avoiding interpretation until the end Free monad, free applicative, finally tagless 17 / 23
  35. i m p o r t c a t s

    . M o n a d / * * T h e i n t e r p r e t e r * / a b s t r a c t c l a s s R W I n t e r p [ F [ _ ] ] { d e f F : M o n a d [ F ] d e f r e a d : F [ S t r i n g ] d e f w r i t e ( s : S t r i n g ) : F [ U n i t ] } 18 / 23
  36. i m p o r t c a t s

    . M o n a d / * * T h e i n t e r p r e t e r * / a b s t r a c t c l a s s R W I n t e r p [ F [ _ ] ] { d e f F : M o n a d [ F ] d e f r e a d : F [ S t r i n g ] d e f w r i t e ( s : S t r i n g ) : F [ U n i t ] } / * * T h e s t r u c t u r e / A S T * / s e a l e d a b s t r a c t c l a s s R W [ A ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ A ] } i m p l i c i t v a l c o n s o l e M o n a d : M o n a d [ R W ] = n e w M o n a d [ R W ] { d e f f l a t M a p [ A , B ] ( f a : R W [ A ] ) ( f : A = > R W [ B ] ) : R W [ B ] = n e w R W [ B ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ B ] = i n t e r p . F . f l a t M a p ( f a . r u n ( i n t e r p ) ) ( a = > f ( a ) . r u n ( i n t e r p ) ) } d e f p u r e [ A ] ( a : A ) : R W [ A ] = n e w R W [ A ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ A ] = i n t e r p . F . p u r e ( a ) } } 18 / 23
  37. v a l r e a d : R W

    [ S t r i n g ] = n e w R W [ S t r i n g ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ S t r i n g ] = i n t e r p . r e a d } d e f w r i t e ( s : S t r i n g ) : R W [ U n i t ] = n e w R W [ U n i t ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ U n i t ] = i n t e r p . w r i t e ( s ) } 19 / 23
  38. v a l r e a d : R W

    [ S t r i n g ] = n e w R W [ S t r i n g ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ S t r i n g ] = i n t e r p . r e a d } d e f w r i t e ( s : S t r i n g ) : R W [ U n i t ] = n e w R W [ U n i t ] { d e f r u n [ F [ _ ] ] ( i n t e r p : R W I n t e r p [ F ] ) : F [ U n i t ] = i n t e r p . w r i t e ( s ) } v a l p r o g = f o r { x < - r e a d y < - r e a d _ < - w r i t e ( x + + y ) } y i e l d ( ) / / p r o g : R W [ U n i t ] = $ a n o n $ 1 $ $ a n o n $ 2 @ e b 4 9 8 c b 19 / 23
  39. i m p o r t c a t s

    . I d i m p o r t s c a l a . i o . S t d I n / * * A n i n t e r p r e t e r t h a t u s e s c o n s o l e I O * / v a l s t d i o I n t e r p = n e w R W I n t e r p [ I d ] { v a l F = i m p l i c i t l y [ M o n a d [ I d ] ] d e f r e a d : S t r i n g = S t d I n . r e a d L i n e ( ) d e f w r i t e ( s : S t r i n g ) : U n i t = p r i n t l n ( s ) } / / s t d i o I n t e r p : R W I n t e r p [ c a t s . I d ] { v a l F : c a t s . M o n a d [ c a t s . I d ] } = $ a n o n $ 1 @ 3 4 e 2 0 d 2 f d e f g o ( ) : U n i t = p r o g . r u n ( s t d i o I n t e r p ) / / g o : ( ) U n i t 20 / 23
  40. i m p o r t c a t s

    . d a t a . S t a t e c a s e c l a s s R W S t a t e ( i n : L i s t [ S t r i n g ] , o u t : L i s t [ S t r i n g ] ) { d e f r e a d : ( R W S t a t e , S t r i n g ) = ( c o p y ( i n = i n . t a i l ) , i n . h e a d ) / / Y O L O d e f w r i t e ( s : S t r i n g ) : ( R W S t a t e , U n i t ) = ( c o p y ( o u t = s : : o u t ) , ( ) ) } / / d e f i n e d c l a s s R W S t a t e / * * A n i n t e r p r e t e r t h a t u s e s t h e S t a t e m o n a d * / v a l s t a t e I n t e r p = n e w R W I n t e r p [ S t a t e [ R W S t a t e , ? ] ] { v a l F = i m p l i c i t l y [ M o n a d [ S t a t e [ R W S t a t e , ? ] ] ] v a l r e a d : S t a t e [ R W S t a t e , S t r i n g ] = S t a t e ( _ . r e a d ) d e f w r i t e ( s : S t r i n g ) : S t a t e [ R W S t a t e , U n i t ] = S t a t e ( c s = > c s . w r i t e ( s ) ) } / / s t a t e I n t e r p : R W I n t e r p [ [ β ] c a t s . d a t a . S t a t e T [ c a t s . E v a l , R W S t a t e , β ] ] { v a l F : c a t s . M o n a d [ [ β ] c a 21 / 23
  41. i m p o r t c a t s

    . d a t a . S t a t e c a s e c l a s s R W S t a t e ( i n : L i s t [ S t r i n g ] , o u t : L i s t [ S t r i n g ] ) { d e f r e a d : ( R W S t a t e , S t r i n g ) = ( c o p y ( i n = i n . t a i l ) , i n . h e a d ) / / Y O L O d e f w r i t e ( s : S t r i n g ) : ( R W S t a t e , U n i t ) = ( c o p y ( o u t = s : : o u t ) , ( ) ) } / / d e f i n e d c l a s s R W S t a t e / * * A n i n t e r p r e t e r t h a t u s e s t h e S t a t e m o n a d * / v a l s t a t e I n t e r p = n e w R W I n t e r p [ S t a t e [ R W S t a t e , ? ] ] { v a l F = i m p l i c i t l y [ M o n a d [ S t a t e [ R W S t a t e , ? ] ] ] v a l r e a d : S t a t e [ R W S t a t e , S t r i n g ] = S t a t e ( _ . r e a d ) d e f w r i t e ( s : S t r i n g ) : S t a t e [ R W S t a t e , U n i t ] = S t a t e ( c s = > c s . w r i t e ( s ) ) } / / s t a t e I n t e r p : R W I n t e r p [ [ β ] c a t s . d a t a . S t a t e T [ c a t s . E v a l , R W S t a t e , β ] ] { v a l F : c a t s . M o n a d [ [ β ] c a v a l c s = R W S t a t e ( L i s t ( " h e l l o " , " n e s c a l a " , " n o t r e a d " ) , L i s t . e m p t y ) / / c s : R W S t a t e = R W S t a t e ( L i s t ( h e l l o , n e s c a l a , n o t r e a d ) , L i s t ( ) ) v a l s t a t e = p r o g . r u n [ S t a t e [ R W S t a t e , ? ] ] ( s t a t e I n t e r p ) / / s t a t e : c a t s . d a t a . S t a t e T [ c a t s . E v a l , R W S t a t e , U n i t ] = c a t s . d a t a . S t a t e T @ 5 2 e f f 0 e 6 v a l r u n S t a t e = s t a t e . r u n S ( c s ) . v a l u e / / r u n S t a t e : R W S t a t e = R W S t a t e ( L i s t ( n o t r e a d ) , L i s t ( h e l l o n e s c a l a ) ) 21 / 23
  42. Summary Functions allow reuse of computation Functions as values allow

    for highly generic combinators Type parameters abstract away unnecessary details 22 / 23
  43. Summary Functions allow reuse of computation Functions as values allow

    for highly generic combinators Type parameters abstract away unnecessary details Abstract type members enforce hiding of irrelevant detail 22 / 23
  44. Summary Functions allow reuse of computation Functions as values allow

    for highly generic combinators Type parameters abstract away unnecessary details Abstract type members enforce hiding of irrelevant detail Higher-kinds allow for higher order abstraction 22 / 23
  45. Summary Functions allow reuse of computation Functions as values allow

    for highly generic combinators Type parameters abstract away unnecessary details Abstract type members enforce hiding of irrelevant detail Higher-kinds allow for higher order abstraction EDSLs separate structure from interpretation, allowing the same structure to be run against multiple interpreters 22 / 23
  46. Summary Functions allow reuse of computation Functions as values allow

    for highly generic combinators Type parameters abstract away unnecessary details Abstract type members enforce hiding of irrelevant detail Higher-kinds allow for higher order abstraction EDSLs separate structure from interpretation, allowing the same structure to be run against multiple interpreters Learn more: "On understanding types, data abstraction, and polymorphism" Luca Cardelli, Peter Wenger "On understanding data abstraction, revisited" William R. Cook "Type Classes vs. the World" Edward Kmett 22 / 23