Asymptotic Improvement of Computations over Free Monads Janis Voigtl¨ ander Technische Universit¨ at Dresden MPC’08
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo 2
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Behaviour: stdin : stdout : 2
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Behaviour: stdin : a stdout : a 2
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Behaviour: stdin : a b stdout : a b 2
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Behaviour: stdin : a b c stdout : a b c 2
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Behaviour: stdin : a b c ∗ stdout : a b c 2
Monads for IO in Haskell Program: echo :: IO () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Behaviour: stdin : a b c ∗ stdout : a b c 2
Testing IO Programs: IOSpec [Swierstra & Altenkirch, 07] Program: echo :: IOSpec Teletype () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo 3
Testing IO Programs: IOSpec [Swierstra & Altenkirch, 07] Program: echo :: IOSpec Teletype () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Testing: > run ( evalIOSpec echo singleThreaded ) “abc ∗ ” 3
Testing IO Programs: IOSpec [Swierstra & Altenkirch, 07] Program: echo :: IOSpec Teletype () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Testing: > run ( evalIOSpec echo singleThreaded ) “abc ∗ ” Read (Print ‘a’ (Read (Print ‘b’ (Read (Print ‘c’ (Read (Finish ()))))))) 3
Testing IO Programs: IOSpec [Swierstra & Altenkirch, 07] Program: echo :: IOSpec Teletype () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Testing: prop cs = run ( evalIOSpec echo singleThreaded ) ( cs + + “ ∗ ”) ≡ copy cs where copy ( c : cs ) = Read (Print c ( copy cs )) copy [ ] = Read (Finish ()) 3
Testing IO Programs: IOSpec [Swierstra & Altenkirch, 07] Program: echo :: IOSpec Teletype () echo = do c ← getChar when ( c � = ‘ ∗ ’) $ do putChar c echo Testing: prop cs = run ( evalIOSpec echo singleThreaded ) ( cs + + “ ∗ ”) ≡ copy cs where copy ( c : cs ) = Read (Print c ( copy cs )) copy [ ] = Read (Finish ()) > quickCheck prop OK, passed 100 tests. 3
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c 4
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Behaviour: stdin : stdout : 4
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Behaviour: stdin : a stdout : 4
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Behaviour: stdin : a b stdout : 4
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Behaviour: stdin : a b c stdout : 4
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Behaviour: stdin : a b c ∗ stdout : c b a 4
A Slight Variation of the Example Program: revEcho :: IO () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Behaviour: stdin : a b c ∗ stdout : c b a 4
A Slight Variation of the Example Program: revEcho :: IOSpec Teletype () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Testing: > run ( evalIOSpec revEcho singleThreaded ) “abc ∗ ” 4
A Slight Variation of the Example Program: revEcho :: IOSpec Teletype () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Testing: > run ( evalIOSpec revEcho singleThreaded ) “abc ∗ ” Read (Read (Read (Read (Print ‘c’ (Print ‘b’ (Print ‘a’ (Finish ()))))))) 4
A Slight Variation of the Example Program: revEcho :: IOSpec Teletype () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Testing: prop cs = run ( evalIOSpec revEcho singleThreaded ) ( cs + + “ ∗ ”) ≡ mirror cs (Finish ()) where mirror ( c : cs ) acc = Read ( mirror cs (Print c acc )) mirror [ ] acc = Read acc 4
A Slight Variation of the Example Program: revEcho :: IOSpec Teletype () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Testing: prop cs = run ( evalIOSpec revEcho singleThreaded ) ( cs + + “ ∗ ”) ≡ mirror cs (Finish ()) where mirror ( c : cs ) acc = Read ( mirror cs (Print c acc )) mirror [ ] acc = Read acc > quickCheck prop OK, passed 100 tests. 4
A Slight Variation of the Example: Ouch! Program: revEcho :: IOSpec Teletype () revEcho = do c ← getChar when ( c � = ‘ ∗ ’) $ do revEcho putChar c Testing: prop cs = run ( evalIOSpec revEcho singleThreaded ) ( cs + + “ ∗ ”) ≡ mirror cs (Finish ()) where mirror ( c : cs ) acc = Read ( mirror cs (Print c acc )) mirror [ ] acc = Read acc > quickCheck prop But each test takes quadratic time! OK, passed 100 tests. 4
But Why? Let’s take a closer look at “IOSpec Teletype”, henceforth “IO tt ”. 5
But Why? Let’s take a closer look at “IOSpec Teletype”, henceforth “IO tt ”. data IO tt α = GetChar (Char → IO tt α ) | PutChar Char (IO tt α ) | Return α 5
But Why? Let’s take a closer look at “IOSpec Teletype”, henceforth “IO tt ”. data IO tt α = GetChar (Char → IO tt α ) | PutChar Char (IO tt α ) | Return α instance Monad IO tt where · · · 5
But Why? Let’s take a closer look at “IOSpec Teletype”, henceforth “IO tt ”. data IO tt α = GetChar (Char → IO tt α ) | PutChar Char (IO tt α ) | Return α instance Monad IO tt where · · · getChar :: IO tt Char getChar = GetChar Return putChar :: Char → IO tt () putChar c = PutChar c (Return ()) 5
But Why? Let’s take a closer look at “IOSpec Teletype”, henceforth “IO tt ”. data IO tt α = GetChar (Char → IO tt α ) | PutChar Char (IO tt α ) | Return α instance Monad IO tt where · · · getChar :: IO tt Char getChar = GetChar Return putChar :: Char → IO tt () putChar c = PutChar c (Return ()) run :: IO tt α → String → Output α run (GetChar f ) ( c : cs ) = Read ( run ( f c ) cs ) run (PutChar c p ) cs = Print c ( run p cs ) run (Return a ) = Finish a cs 5
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a run “abc ∗ ” revEcho 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a run “abc ∗ ” revEcho 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a run GetChar f “abc ∗ ” 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a run GetChar f “abc ∗ ” run (GetChar f ) ( c : cs ) = Read ( run ( f c ) cs ) 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a Read run > > “bc ∗ ” putChar ‘a’ revEcho run (GetChar f ) ( c : cs ) = Read ( run ( f c ) cs ) 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a Read run > > “bc ∗ ” putChar ‘a’ revEcho run (GetChar f ) ( c : cs ) = Read ( run ( f c ) cs ) 6
But Why? Now, revEcho desugared and with some inlining: revEcho :: IO tt () revEcho = GetChar f where f = λ c → when ( c � = ‘ ∗ ’) $ revEcho > > putChar c An example evaluation, counting (certain) steps: a Read run > > “bc ∗ ” GetChar f putChar ‘a’ run (GetChar f ) ( c : cs ) = Read ( run ( f c ) cs ) 6
Recommend
More recommend