Slide 1

Slide 1 text

functional parser of markdown language based on monad combining and monoidal source stream representation . Georgiy Lukjanov ([email protected]) Assistant professor Artem Pelenitsin ([email protected]) TMPA conference, 3 Feb 2017 Southern Federal University, Rostov-on-Don, Russia

Slide 2

Slide 2 text

Goals . ∙ Explore approaches to structuring of computation with multiple side-effects provided by modern Haskell libraries 2 / 22

Slide 3

Slide 3 text

Goals . ∙ Explore approaches to structuring of computation with multiple side-effects provided by modern Haskell libraries ∙ Monad Transformers 2 / 22

Slide 4

Slide 4 text

Goals . ∙ Explore approaches to structuring of computation with multiple side-effects provided by modern Haskell libraries ∙ Monad Transformers ∙ Algebraic effects and effects handlers (specifically Extensible Effects) 2 / 22

Slide 5

Slide 5 text

Goals . ∙ Explore approaches to structuring of computation with multiple side-effects provided by modern Haskell libraries ∙ Monad Transformers ∙ Algebraic effects and effects handlers (specifically Extensible Effects) ∙ As a case study, build parsers combinators libraries and restricted Markdown parsers using these approaches 2 / 22

Slide 6

Slide 6 text

Goals . ∙ Explore approaches to structuring of computation with multiple side-effects provided by modern Haskell libraries ∙ Monad Transformers ∙ Algebraic effects and effects handlers (specifically Extensible Effects) ∙ As a case study, build parsers combinators libraries and restricted Markdown parsers using these approaches ∙ Compare these approaches in terms of expressibility and performance 2 / 22

Slide 7

Slide 7 text

Parsers . Informal definition A parser is a program that converts text into some kind of AST (abstract syntax tree) 3 / 22

Slide 8

Slide 8 text

Parsers . Informal definition A parser is a program that converts text into some kind of AST (abstract syntax tree) ∙ Auto-generated, by bottom-up parser generators (YACC) 3 / 22

Slide 9

Slide 9 text

Parsers . Informal definition A parser is a program that converts text into some kind of AST (abstract syntax tree) ∙ Auto-generated, by bottom-up parser generators (YACC) ∙ Manually-written (e.g. top-down recursive descent) 3 / 22

Slide 10

Slide 10 text

Parser Combinators . ∙ Model parsers as higher-order functions map :: (a → b) → [a] → [b] map [ ] = [ ] map f (x : xs) = f x : map f xs 4 / 22

Slide 11

Slide 11 text

Parser Combinators . ∙ Model parsers as higher-order functions map :: (a → b) → [a] → [b] map [ ] = [ ] map f (x : xs) = f x : map f xs ∙ Construct complex parsers from small set of basic ones alphanum :: Parser r Char alphanum = letter <|> digit 4 / 22

Slide 12

Slide 12 text

Parser Combinators . ∙ Model parsers as higher-order functions map :: (a → b) → [a] → [b] map [ ] = [ ] map f (x : xs) = f x : map f xs ∙ Construct complex parsers from small set of basic ones alphanum :: Parser r Char alphanum = letter <|> digit ∙ Mirror grammar rules in source code of the parser 4 / 22

Slide 13

Slide 13 text

Parser as a Monad . Parser data type newtype Parser a = Parser { parse :: String → Maybe (a, String)} 5 / 22

Slide 14

Slide 14 text

Parser as a Monad . Parser data type newtype Parser a = Parser { parse :: String → Maybe (a, String)} Monad instance for Parser instance Monad Parser where return t = Parser $ λs → Just (t, s) m > > = k = Parser $ λs → do (u, v) ← parse m s (x, y) ← parse (k u) v return (x, y) 5 / 22

Slide 15

Slide 15 text

Types and Effects: main notions . ∙ Pure/Impure functions and referential transparency 6 / 22

Slide 16

Slide 16 text

Types and Effects: main notions . ∙ Pure/Impure functions and referential transparency Pure function show :: (Show a) ⇒ a → String 6 / 22

Slide 17

Slide 17 text

Types and Effects: main notions . ∙ Pure/Impure functions and referential transparency Pure function show :: (Show a) ⇒ a → String IO action putStrLn :: String → IO () 6 / 22

Slide 18

Slide 18 text

Types and Effects: main notions . ∙ Static guarantees on computations permissions 7 / 22

Slide 19

Slide 19 text

Types and Effects: main notions . ∙ Static guarantees on computations permissions Computation with static environment readUser :: (MonadReader Database m) ⇒ UserID → m UserData 7 / 22

Slide 20

Slide 20 text

Types and Effects: main notions . ∙ Static guarantees on computations permissions Computation with static environment readUser :: (MonadReader Database m) ⇒ UserID → m UserData ∙ Combining multiple effects 7 / 22

Slide 21

Slide 21 text

Types and Effects: main notions . ∙ Static guarantees on computations permissions Computation with static environment readUser :: (MonadReader Database m) ⇒ UserID → m UserData ∙ Combining multiple effects Static environment and ‘mutable’ state handler :: (MonadReader Config m , MonadState Database m) ⇒ m a 7 / 22

Slide 22

Slide 22 text

Haskell frameworks for effects typing . Monad Transformers — type class based class (Monad m) ⇒ MonadState m where get :: m (StateType m) put :: StateType m → m () newtype StateT s m a = StateT {runStateT :: s → m (a, s)} instance (Monad m) ⇒ MonadState (StateT s m) where get = StateT $ λs → return (s, s) put s = StateT $ \_ → return ((), s) instance MonadTrans (StateT s) where ... instance (MonadIO m) ⇒ MonadIO (StateT s m) where ... 8 / 22

Slide 23

Slide 23 text

Haskell frameworks for effects typing . Extensible Effects — free monad based data Free f a where Pure :: a → Free f a Impure :: f (Free f a) → Free f a data State s v where Get :: State s s Put :: !s → State s () instance Functor (State s) type FState s = Free (State s) 9 / 22

Slide 24

Slide 24 text

Parser as a monadic stack . Parser newtype Parser a = Parser (StateT String Maybe a) 10 / 22

Slide 25

Slide 25 text

Parser as a monadic stack . Parser newtype Parser a = Parser (StateT String Maybe a) Running a parser parse :: Parser a → String → Maybe (a, String t) parse (Parser p) s = runStateT p s 10 / 22

Slide 26

Slide 26 text

Parser as a Union of Effects . type Parsable r = (Member Fail r, Member (State String) r) type Parser r a = Parsable r ⇒ Eff r a 11 / 22

Slide 27

Slide 27 text

Parser as a Union of Effects . type Parsable r = (Member Fail r, Member (State String) r) type Parser r a = Parsable r ⇒ Eff r a Running a parser (handling effects) parse :: Eff (Fail ’: State String ’ : [ ]) a → String → (Either () a, String) parse p inp = run $ runState (runError p) inp 11 / 22

Slide 28

Slide 28 text

Basic parsers . Unconditional consumer item :: Parser r Char item = do s ← get case s of [ ] → put s > > die (x : xs) → put xs > > pure x 12 / 22

Slide 29

Slide 29 text

Basic parsers . Unconditional consumer item :: Parser r Char item = do s ← get case s of [ ] → put s > > die (x : xs) → put xs > > pure x Conditional consumer sat :: (Char → Bool) → Parser r Char sat p = do x ← item if p x then return x else die 12 / 22

Slide 30

Slide 30 text

Parsers combinators . Determenistic alternative combinator alt :: Parser r a → Parser r a → Parser r a alt ma mb = do s ← get catchExc ma $ λea → put s > > catchExc mb $ λeb → die 13 / 22

Slide 31

Slide 31 text

Parsers combinators . Determenistic alternative combinator alt :: Parser r a → Parser r a → Parser r a alt ma mb = do s ← get catchExc ma $ λea → put s > > catchExc mb $ λeb → die Repetition combinator many :: Parser r a → Parser r [a] many v = many_v where many_v = some_v ‘alt‘ (pure [ ]) some_v = (fmap (:) v) < ∗ > many_v 13 / 22

Slide 32

Slide 32 text

Restricted Markdown AST . Document type Document = [Block] Block data Block = Blank | Header (Int, Line) | Paragraph [Line] | UnorderedList [Line] | BlockQuote [Line] 14 / 22

Slide 33

Slide 33 text

Constructing AST . Parser for Document doc :: Parser Document doc = many block where block = blank <|> header <|> paragraph <|> unorderdList <|> blockquote <|> blockMath Parser for headers header :: Parser Block header = do hashes ← token $ some $ char ’#’ text ← nonEmptyLine return $ Header (length hashes, text) 15 / 22

Slide 34

Slide 34 text

Performance benchmarks. MTL . Estimate Confidence interval Mean time 121 μs [119 μs, 126 μs] σ 10.0 μs [20.2 μs, 3.84 μs] 16 / 22

Slide 35

Slide 35 text

Performance benchmarks. Freer EE . Estimate Confidence interval Mean time 7.53 ms [7.44 ms, 7.66 ms] σ 289 μs [194 μs, 436 μs] 17 / 22

Slide 36

Slide 36 text

String-like types in Haskell . String Essentially a [Char] — poor performance ByteString High performance, but low-level interface Text Unicode-oriented high performance type 18 / 22

Slide 37

Slide 37 text

Text-oriented Monoids . Input-polymorphic base parser item :: TextualMonoid t ⇒ Parser t Char item = do s ← splitCharacterPrefix ◦ remainder < $ > get case s of Nothing → throwError Just (c, rest) → put rest ∗ > pure c ‘uncons’-like function splitCharacterPrefix :: TextualMonoid t ⇒ t → Maybe (Char, t) 19 / 22

Slide 38

Slide 38 text

Conclusion and results . 1. Parsers combinators library and Markdown parser based on Monad Transformers. ∙ https://github.com/geo2a/markdown_monparsing 2. Parsers combinators library and Markdown parser based on Extensible Effects. ∙ https://github.com/geo2a/ext-effects-parsers ∙ https://github.com/geo2a/ext-effects-markdown 3. Performance comparison of Monad Transformers and Extensible Effects based libraries. 20 / 22

Slide 39

Slide 39 text

References . ∙ Monadic Parser Combinators // Graham Hutton, Erik Meijer – Department of Computer Science, University of Nottingham, 1996 ∙ Adding Structure to Monoids // Mario Blaževic – Stilo International plc ∙ Extensible Effects An Alternative to Monad Transformers // Oleg Kiselyov, Amr Sabry, Cameron Swords – Indiana University, USA ∙ Freer monads and more extensible effects // Oleg Kiselyov, Hiromi Ishii 21 / 22

Slide 40

Slide 40 text

Questions? . Results outline 1. Parsers combinators library and Markdown parser based on Monad Transformers. 2. Parsers combinators library and Markdown parser based on Extensible Effects. 3. Performance comparison of Monad Transformers and Extensible Effects based libraries. Georgiy Lukyanov [email protected] Artem Pelenitsin [email protected] 22 / 22