Last active
April 26, 2022 02:53
-
-
Save crvdgc/1cf08172f5e0c1e0802b4628b2852395 to your computer and use it in GitHub Desktop.
FP101x monadic parser example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.Char (isDigit) | |
data Parser a = Parser (String -> [(a, String)]) | |
instance Functor Parser where | |
fmap f (Parser pa) = Parser $ \inp -> | |
flip fmap (pa inp) $ \(a, out) -> (f a, out) | |
instance Applicative Parser where | |
pure a = Parser $ \inp -> [(a, inp)] | |
(Parser pf) <*> (Parser pa) = Parser $ \inp -> | |
concat . flip fmap (pf inp) $ \(f, out) -> | |
flip fmap (pa out) $ \(a, out') -> | |
(f a, out') | |
instance Monad Parser where | |
(Parser pa) >>= f = Parser $ \inp -> | |
concat . flip fmap (pa inp) $ \(a, out) -> | |
let (Parser pb) = f a | |
in pb out | |
item :: Parser Char | |
item = Parser $ \inp -> case inp of | |
[] -> [] | |
(x:xs) -> [(x,xs)] | |
failure :: Parser a | |
failure = Parser $ \inp -> [] | |
(+++) :: Parser a -> Parser a -> Parser a | |
p +++ q = Parser $ \inp -> | |
case parse p inp of | |
[] -> parse q inp | |
[(v, out)] -> [(v, out)] | |
parse :: Parser a -> String -> [(a, String)] | |
parse (Parser p) inp = p inp | |
sat :: (Char -> Bool) -> Parser Char | |
sat p = do | |
x <- item | |
if p x | |
then return x | |
else failure | |
digit :: Parser Char | |
digit = sat isDigit | |
char :: Char -> Parser Char | |
char x = sat (x ==) | |
many :: Parser a -> Parser [a] | |
many p = many1 p +++ return [] | |
many1 :: Parser a -> Parser [a] | |
many1 p = do | |
v <- p | |
vs <- many p | |
return (v:vs) | |
string :: String -> Parser String | |
string [] = return [] | |
string (x:xs) = do | |
char x | |
string xs | |
return (x:xs) | |
p :: Parser String | |
p = do | |
char '[' | |
d <- digit | |
ds <- many (do char ',' | |
digit) | |
char ']' | |
return (d:ds) | |
main = do | |
print $ parse item "" -- should output: [] | |
print $ parse item "abc" -- [('a', "bc")] | |
print $ parse p "[1,2,3,4]" -- [("1234","")] | |
print $ parse p "[1,2,3,4" -- [] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment