# Parsing expressions with combinators

I’m very new to Haskell’s ReadP library, and the entire concept of parser combinators, so I was wondering whether there are better ways to do some things in this program:

``import Text.ParserCombinators.ReadP import Control.Applicative import Data.List  data Operator = Add | Subtract  instance Show Operator where     show Add = "+"     show Subtract = "-"  instance Read Operator where     readsPrec _ "+" = [(Add, "")]     readsPrec _ "-" = [(Subtract, "")]     readsPrec _ _ = []  data Expression = Number Int                 | Infix { left :: Expression, op :: Operator, right :: Expression }  instance Show Expression where     show (Number x) = show x     show (Infix left op right) = "(" ++ (show left) ++ " " ++ (show op) ++ " " ++ (show right) ++ ")"  digit :: ReadP Char digit = satisfy \$   \char -> char >= '0' && char <= '9'  number :: ReadP Expression number = fmap (Number . read) (many1 digit)  operator :: ReadP Operator operator = fmap read (string "+" <|> string "-")  expression :: ReadP Expression expression = do     skipSpaces     left <- number     skipSpaces     op <- Control.Applicative.optional operator     case op of         Nothing -> return left         Just op -> do             skipSpaces             right <- expression             return (Infix left op right)  parseExpression :: String -> Maybe Expression parseExpression input = case readP_to_S expression input of     [] -> Nothing     xs -> (Just . fst . last) xs ``

The main area where I’m looking for improvements is the `expression` function, and specifically the things which seem improvable are the repeated calls to `skipSpaces` and the case expression to check whether an operator was parsed, but of course if you notice anything else that would be helpful too!

Posted on Categories buy elite proxies
{"ft_lang_label":"__label__en","ft_lang_prob":0.77046835,"math_prob":0.9581186,"size":1613,"snap":"2019-13-2019-22","text_gpt3_token_len":361,"char_repetition_ratio":0.15786202,"word_repetition_ratio":0.0072727273,"special_character_ratio":0.2802232,"punctuation_ratio":0.13565892,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.99451137,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-03-22T02:59:10Z\",\"WARC-Record-ID\":\"<urn:uuid:08cbb083-d9bf-4d86-8b68-27027c213695>\",\"Content-Length\":\"24230\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:b8a7bb29-4c96-46fd-ac25-a8e168f0be34>\",\"WARC-Concurrent-To\":\"<urn:uuid:6cd32033-b127-42ed-b81c-94fea4f6ce89>\",\"WARC-IP-Address\":\"173.212.203.156\",\"WARC-Target-URI\":\"https://proxieslive.com/parsing-expressions-with-combinators/\",\"WARC-Payload-Digest\":\"sha1:CDVF46ZA2PV5KSG7KUIZFRXNYIKD456L\",\"WARC-Block-Digest\":\"sha1:54VLZHHPPSUYHAVQZXYOVDWYO5JOQKSX\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-13/CC-MAIN-2019-13_segments_1552912202589.68_warc_CC-MAIN-20190322014319-20190322040319-00076.warc.gz\"}"}