TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source...

40
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

Transcript of TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source...

Page 1: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

functional parser of markdownlanguage based on monad combiningand monoidal source streamrepresentation.

Georgiy Lukjanov ([email protected])Assistant professor Artem Pelenitsin ([email protected])

TMPA conference, 3 Feb 2017

Southern Federal University, Rostov-on-Don, Russia

Page 2: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Goals.

∙ Explore approaches to structuring of computation withmultiple side-effects provided by modern Haskelllibraries

∙ Monad Transformers∙ Algebraic effects and effects handlers (specificallyExtensible Effects)

∙ As a case study, build parsers combinators librariesand restricted Markdown parsers using theseapproaches

∙ Compare these approaches in terms of expressibilityand performance

2 / 22

Page 3: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Goals.

∙ Explore approaches to structuring of computation withmultiple side-effects provided by modern Haskelllibraries∙ Monad Transformers

∙ Algebraic effects and effects handlers (specificallyExtensible Effects)

∙ As a case study, build parsers combinators librariesand restricted Markdown parsers using theseapproaches

∙ Compare these approaches in terms of expressibilityand performance

2 / 22

Page 4: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Goals.

∙ Explore approaches to structuring of computation withmultiple side-effects provided by modern Haskelllibraries∙ Monad Transformers∙ Algebraic effects and effects handlers (specificallyExtensible Effects)

∙ As a case study, build parsers combinators librariesand restricted Markdown parsers using theseapproaches

∙ Compare these approaches in terms of expressibilityand performance

2 / 22

Page 5: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Goals.

∙ Explore approaches to structuring of computation withmultiple side-effects provided by modern Haskelllibraries∙ Monad Transformers∙ Algebraic effects and effects handlers (specificallyExtensible Effects)

∙ As a case study, build parsers combinators librariesand restricted Markdown parsers using theseapproaches

∙ Compare these approaches in terms of expressibilityand performance

2 / 22

Page 6: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Goals.

∙ Explore approaches to structuring of computation withmultiple side-effects provided by modern Haskelllibraries∙ Monad Transformers∙ Algebraic effects and effects handlers (specificallyExtensible Effects)

∙ As a case study, build parsers combinators librariesand restricted Markdown parsers using theseapproaches

∙ Compare these approaches in terms of expressibilityand performance

2 / 22

Page 7: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parsers.

Informal definition

A parser is a program that converts text into some kind ofAST (abstract syntax tree)

∙ Auto-generated, by bottom-up parser generators (YACC)∙ Manually-written (e.g. top-down recursive descent)

3 / 22

Page 8: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parsers.

Informal definition

A parser is a program that converts text into some kind ofAST (abstract syntax tree)

∙ Auto-generated, by bottom-up parser generators (YACC)

∙ Manually-written (e.g. top-down recursive descent)

3 / 22

Page 9: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parsers.

Informal definition

A parser is a program that converts text into some kind ofAST (abstract syntax tree)

∙ Auto-generated, by bottom-up parser generators (YACC)∙ Manually-written (e.g. top-down recursive descent)

3 / 22

Page 10: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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 Charalphanum = letter <|> digit

∙ Mirror grammar rules in source code of the parser

4 / 22

Page 11: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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 Charalphanum = letter <|> digit

∙ Mirror grammar rules in source code of the parser

4 / 22

Page 12: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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 Charalphanum = letter <|> digit

∙ Mirror grammar rules in source code of the parser

4 / 22

Page 13: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parser as a Monad.

Parser data type

newtype Parser a = Parser {parse :: String→ Maybe (a, String)}

Monad instance for Parserinstance 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) vreturn (x, y)

5 / 22

Page 14: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parser as a Monad.

Parser data type

newtype Parser a = Parser {parse :: String→ Maybe (a, String)}

Monad instance for Parserinstance 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) vreturn (x, y) 5 / 22

Page 15: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 16: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 17: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 18: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 19: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 20: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 21: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 22: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Haskell frameworks for effects typing.

Monad Transformers — type class based

class (Monad m)⇒ MonadState m whereget ::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) whereget = 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

Page 23: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Haskell frameworks for effects typing.

Extensible Effects — free monad based

data Free f a wherePure :: a→ Free f aImpure :: f (Free f a)→ Free f a

data State s v whereGet :: State s sPut :: !s→ State s ()

instance Functor (State s)

type FState s = Free (State s)

9 / 22

Page 24: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 25: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 26: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 27: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

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

Page 28: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Basic parsers.

Unconditional consumer

item :: Parser r Charitem = do s← get

case s of [ ]→ put s>> die(x : xs)→ put xs>> pure x

Conditional consumer

sat :: (Char→ Bool)→ Parser r Charsat p = do x← item

if p x then return x else die

12 / 22

Page 29: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Basic parsers.

Unconditional consumer

item :: Parser r Charitem = do s← get

case s of [ ]→ put s>> die(x : xs)→ put xs>> pure x

Conditional consumer

sat :: (Char→ Bool)→ Parser r Charsat p = do x← item

if p x then return x else die12 / 22

Page 30: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parsers combinators.

Determenistic alternative combinator

alt :: Parser r a→ Parser r a→ Parser r aalt 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_vwhere many_v = some_v ‘alt‘ (pure [ ])

some_v = (fmap (:) v)< ∗ >many_v

13 / 22

Page 31: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Parsers combinators.

Determenistic alternative combinator

alt :: Parser r a→ Parser r a→ Parser r aalt 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_vwhere many_v = some_v ‘alt‘ (pure [ ])

some_v = (fmap (:) v)< ∗ >many_v 13 / 22

Page 32: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Restricted Markdown AST.

Document

type Document = [Block]

Block

data Block = Blank| Header (Int, Line)| Paragraph [Line]| UnorderedList [Line]| BlockQuote [Line]

14 / 22

Page 33: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Constructing AST.

Parser for Documentdoc :: Parser Documentdoc = many block

where block = blank <|> header <|> paragraph<|> unorderdList <|> blockquote<|> blockMath

Parser for headersheader :: Parser Blockheader = do

hashes← token $ some $ char ’#’text ← nonEmptyLinereturn $ Header (length hashes, text) 15 / 22

Page 34: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Performance benchmarks. MTL.

Estimate Confidence intervalMean time 121 μs [119 μs, 126 μs]

σ 10.0 μs [20.2 μs, 3.84 μs]

16 / 22

Page 35: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Performance benchmarks. Freer EE.

Estimate Confidence intervalMean time 7.53 ms [7.44 ms, 7.66 ms]

σ 289 μs [194 μs, 436 μs]

17 / 22

Page 36: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

String-like types in Haskell.

StringEssentially a [Char] — poor performance

ByteStringHigh performance, but low-level interface

TextUnicode-oriented high performance type

18 / 22

Page 37: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Text-oriented Monoids.

Input-polymorphic base parser

item :: TextualMonoid t⇒ Parser t Charitem = dos← splitCharacterPrefix ◦ remainder< $ > getcase s of Nothing→ throwError

Just (c, rest)→ put rest ∗ > pure c

‘uncons’-like function

splitCharacterPrefix :: TextualMonoid t⇒t→ Maybe (Char, t)

19 / 22

Page 38: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Conclusion and results.

1. Parsers combinators library and Markdown parserbased on Monad Transformers.∙ https://github.com/geo2a/markdown_monparsing

2. Parsers combinators library and Markdown parserbased on Extensible Effects.∙ https://github.com/geo2a/ext-effects-parsers∙ https://github.com/geo2a/ext-effects-markdown

3. Performance comparison of Monad Transformers andExtensible Effects based libraries.

20 / 22

Page 39: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

References.

∙ Monadic Parser Combinators // Graham Hutton, ErikMeijer – Department of Computer Science, University ofNottingham, 1996

∙ Adding Structure to Monoids // Mario Blaževic – StiloInternational plc

∙ Extensible Effects An Alternative to MonadTransformers // Oleg Kiselyov, Amr Sabry, CameronSwords – Indiana University, USA

∙ Freer monads and more extensible effects // OlegKiselyov, Hiromi Ishii

21 / 22

Page 40: TMPA-2017: Functional Parser of Markdown Language Based on Monad Combining and Monoidal Source Stream Representation

Questions?.

Results outline

1. Parsers combinators library and Markdown parserbased on Monad Transformers.

2. Parsers combinators library and Markdown parserbased on Extensible Effects.

3. Performance comparison of Monad Transformers andExtensible Effects based libraries.

Georgiy Lukyanov [email protected] Pelenitsin [email protected]

22 / 22