Upload
iosif-itkin
View
146
Download
0
Embed Size (px)
Citation preview
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Restricted Markdown AST.
Document
type Document = [Block]
Block
data Block = Blank| Header (Int, Line)| Paragraph [Line]| UnorderedList [Line]| BlockQuote [Line]
14 / 22
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
Performance benchmarks. MTL.
Estimate Confidence intervalMean time 121 μs [119 μs, 126 μs]
σ 10.0 μs [20.2 μs, 3.84 μs]
16 / 22
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
String-like types in Haskell.
StringEssentially a [Char] — poor performance
ByteStringHigh performance, but low-level interface
TextUnicode-oriented high performance type
18 / 22
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
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
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
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