parametricity for haskell with imprecise error semantics
play

Parametricity for Haskell with Imprecise Error Semantics Florian - PowerPoint PPT Presentation

Parametricity for Haskell with Imprecise Error Semantics Florian Stenger 1 and Janis Voigtl ander Technische Universit at Dresden TLCA09 = Applications 1 Supported by the DFG under grant VO 1512/1-1. Parametricity for Haskell with


  1. Parametricity for Haskell with Imprecise Error Semantics Florian Stenger 1 and Janis Voigtl¨ ander Technische Universit¨ at Dresden TLCA’09 = Applications 1 Supported by the DFG under grant VO 1512/1-1.

  2. Parametricity for Haskell with Imprecise Error Semantics Florian Stenger 1 and Janis Voigtl¨ ander Technische Universit¨ at Dresden TLCA’09 = Applications 1 Supported by the DFG under grant VO 1512/1-1.

  3. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] 1

  4. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) 1

  5. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) For every choice of p , f , and l : takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) Provable by induction. 1

  6. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) For every choice of p , f , and l : takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) Provable by induction. Or as a “free theorem” [Wadler, FPCA’89]. 1

  7. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) For every choice of p , f , and l : takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) Provable by induction. Or as a “free theorem” [Wadler, FPCA’89]. 1

  8. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] filter :: ( α → Bool) → [ α ] → [ α ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) For every choice of p , f , and l : takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) filter p ( map f l ) = map f ( filter ( p ◦ f ) l ) 1

  9. Reasoning in Haskell: An Example takeWhile :: ( α → Bool) → [ α ] → [ α ] filter :: ( α → Bool) → [ α ] → [ α ] g :: ( α → Bool) → [ α ] → [ α ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) For every choice of p , f , and l : takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) filter p ( map f l ) = map f ( filter ( p ◦ f ) l ) g p ( map f l ) = map f ( g ( p ◦ f ) l ) 1

  10. Errors in Haskell 2

  11. Errors in Haskell ◮ let average l = div ( sum l ) ( length l ) in average [ ] 2

  12. Errors in Haskell ◮ let average l = div ( sum l ) ( length l ) in average [ ] ◮ let tail ( a : as ) = as in tail [ ] 2

  13. Errors in Haskell ◮ let average l = div ( sum l ) ( length l ) in average [ ] ◮ let tail ( a : as ) = as in tail [ ] ◮ if · · · then error “some string” else · · · 2

  14. Errors in Haskell ◮ let average l = div ( sum l ) ( length l ) in average [ ] ◮ let tail ( a : as ) = as in tail [ ] ◮ if · · · then error “some string” else · · · ◮ let loop = loop in loop 2

  15. Errors in Haskell ◮ let average l = div ( sum l ) ( length l ) in average [ ] ◮ let tail ( a : as ) = as in tail [ ] ◮ if · · · then error “some string” else · · · ◮ let loop = loop in loop Traditionally, all error causes subsumed under “ ⊥ ”. 2

  16. Errors in Haskell ◮ let average l = div ( sum l ) ( length l ) in average [ ] ◮ let tail ( a : as ) = as in tail [ ] ◮ if · · · then error “some string” else · · · ◮ let loop = loop in loop Traditionally, all error causes subsumed under “ ⊥ ”. Better, explicit distinction. Like: Ok v : nonerroneous Bad “ · · · ” : finitely failing ⊥ : nonterminating 2

  17. Naive Propagation of Errors ◮ tail [1 / 0 , 2 . 5] � Ok (( Ok 2 . 5) : ( Ok [ ])) 3

  18. Naive Propagation of Errors ◮ tail [1 / 0 , 2 . 5] � Ok (( Ok 2 . 5) : ( Ok [ ])) ◮ ( λ x → 3) ( error “ · · · ”) � Ok 3 3

  19. Naive Propagation of Errors ◮ tail [1 / 0 , 2 . 5] � Ok (( Ok 2 . 5) : ( Ok [ ])) ◮ ( λ x → 3) ( error “ · · · ”) � Ok 3 ◮ ( error s ) ( · · · ) � Bad s 3

  20. Naive Propagation of Errors ◮ tail [1 / 0 , 2 . 5] � Ok (( Ok 2 . 5) : ( Ok [ ])) ◮ ( λ x → 3) ( error “ · · · ”) � Ok 3 ◮ ( error s ) ( · · · ) � Bad s ◮ case ( error s ) of {· · · } � Bad s 3

  21. Naive Propagation of Errors ◮ tail [1 / 0 , 2 . 5] � Ok (( Ok 2 . 5) : ( Ok [ ])) ◮ ( λ x → 3) ( error “ · · · ”) � Ok 3 ◮ ( error s ) ( · · · ) � Bad s ◮ case ( error s ) of {· · · } � Bad s ◮ ( error s 1 ) + ( error s 2 ) � ??? 3

  22. Naive Propagation of Errors ◮ tail [1 / 0 , 2 . 5] � Ok (( Ok 2 . 5) : ( Ok [ ])) ◮ ( λ x → 3) ( error “ · · · ”) � Ok 3 ◮ ( error s ) ( · · · ) � Bad s ◮ case ( error s ) of {· · · } � Bad s ◮ ( error s 1 ) + ( error s 2 ) � ??? Dependence on evaluation order leads to considerably less freedom for implementors to rearrange computations, to optimise! 3

  23. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Basic idea: Ok v : nonerroneous Bad {· · · } : finitely failing, nondeterministic ⊥ : nonterminating 4

  24. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Basic idea: Ok v : nonerroneous Bad {· · · } : finitely failing, nondeterministic ⊥ : nonterminating Definedness order: Ok Bad ⊥ 4

  25. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Basic idea: Ok v : nonerroneous Bad {· · · } : finitely failing, nondeterministic ⊥ : nonterminating Definedness order: Bad e 2 e 2 ⊆ e 1 Bad e 1 Ok Bad ⊥ 4

  26. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Actual Propagation of Errors: ◮ ( error s 1 ) + ( error s 2 ) � Bad { s 1 , s 2 } 5

  27. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Actual Propagation of Errors: ◮ ( error s 1 ) + ( error s 2 ) � Bad { s 1 , s 2 } ◮ 3 + ( error s ) � Bad { s } 5

  28. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Actual Propagation of Errors: ◮ ( error s 1 ) + ( error s 2 ) � Bad { s 1 , s 2 } ◮ 3 + ( error s ) � Bad { s } ◮ loop + ( error s ) � ⊥ 5

  29. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Actual Propagation of Errors: ◮ ( error s 1 ) + ( error s 2 ) � Bad { s 1 , s 2 } ◮ 3 + ( error s ) � Bad { s } ◮ loop + ( error s ) � ⊥ ◮ ( error s 1 ) ( error s 2 ) � Bad { s 1 , s 2 } 5

  30. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Actual Propagation of Errors: ◮ ( error s 1 ) + ( error s 2 ) � Bad { s 1 , s 2 } ◮ 3 + ( error s ) � Bad { s } ◮ loop + ( error s ) � ⊥ ◮ ( error s 1 ) ( error s 2 ) � Bad { s 1 , s 2 } ◮ ( λ x → 3) ( error s ) � Ok 3 5

  31. Imprecise Error Semantics [Peyton Jones et al., PLDI’99] Actual Propagation of Errors: ◮ ( error s 1 ) + ( error s 2 ) � Bad { s 1 , s 2 } ◮ 3 + ( error s ) � Bad { s } ◮ loop + ( error s ) � ⊥ ◮ ( error s 1 ) ( error s 2 ) � Bad { s 1 , s 2 } ◮ ( λ x → 3) ( error s ) � Ok 3 ◮ case ( error s 1 ) of { ( x , y ) → error s 2 } � Bad { s 1 , s 2 } 5

  32. Impact on Program Equivalence “Normally”: takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) where: takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) 6

  33. Impact on Program Equivalence “Normally”: takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) where: takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) But now: takeWhile null ( map tail ( error s )) � = map tail ( takeWhile ( null ◦ tail ) ( error s )) 6

  34. Impact on Program Equivalence “Normally”: takeWhile p ( map f l ) = map f ( takeWhile ( p ◦ f ) l ) where: takeWhile :: ( α → Bool) → [ α ] → [ α ] takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] map :: ( α → β ) → [ α ] → [ β ] map f [ ] = [ ] map f ( a : as ) = ( f a ) : ( map f as ) But now: takeWhile null ( map tail ( error s )) � s � = map tail ( takeWhile ( null ◦ tail ) ( error s )) � s or � “empty list” 6

  35. Impact on Program Equivalence Because: takeWhile ( null ◦ tail ) ( error s ) � Bad { s , “empty list” } where: takeWhile p [ ] = [ ] takeWhile p ( a : as ) | p a = a : ( takeWhile p as ) | otherwise = [ ] tail [ ] = error “empty list” tail ( a : as ) = as null [ ] = True null ( a : as ) = False 7

Recommend


More recommend