patternMinor
Multiple base numbers parser
Viewed 0 times
parsernumbersmultiplebase
Problem
This code is a Parser that parses numbers according to
It is working at the moment, the only problem is the
R5RS. - #b1001 - binary
- #o2127 - octal
- #h02d - hexadecimal
- #d1231 - decimal
- 3923 - decimal
It is working at the moment, the only problem is the
parseNumberBase. I am really new to haskell, but it does not look very good to me.- How could I improve it? (readability wise)
- It would also be nice to see a more "idiomatic" approach
import Data.Char (digitToInt)
import Numeric (readInt, readOct, readHex)
import Data.Maybe (listToMaybe, fromJust)
parseNumber :: Parser LispVal
parseNumber = parseNumberBase 'd'
do char '#'
base Parser LispVal
parseNumberBase 'b' =
do digits Maybe Integer
readBinary =
fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToIntSolution
do
digits <- someParser
return $ someFunction digitsis just
someFunction someParserWe can make
parseNumberBase a lot shorter with that information:-- | Parses a number at a specific base
parseNumberBase :: Char -> Parser LispVal
parseNumberBase 'b' = Number . fromJust . readBinary many1 (oneOf "01")
parseNumberBase 'o' = Number . fst . head . readOct many1 octDigit -- see below
parseNumberBase 'd' = Number . read many1 digit
parseNumberBase 'h' = Number . fst . head . readHex many1 hexDigit -- see below
parseNumberBase _ = error "Wrong number base"readFunc digits !! 0 is head (readFunc digits), so we were able to get rid of !! too.That being said,
parseNumberBase has a lot of responsibility. Split it into multiple parsers, and it's suddenly a lot easier to grasp:parseBinary :: Parser LispVal
parseBinary = Number . fromJust . readBinary many1 (oneOf "01")
parseDecimal :: Parser LispVal
parseDecimal = Number . read many1 digit
parseHexadecimal :: Parser LispVal
parseHexadecimal = Number . fst . head . readHex many1 hexDigit
parseOct :: Parser LispVal
parseOct = Number . fst . head . readOct many1 octDigitWe can now test all those functions in isolation. We can now write
parseNumberBase as another parser:parseNumber :: Parser LispVal
parseNumber = parseDecimal char '#' *> parseNumberBase
parseNumberBase :: Parser LispVal
parseNumberBase = char 'h' *> parseHexadecimal
char 'd' *> parseDecimal
char 'o' *> parseOct
char 'b' *> parseBinaryCode Snippets
do
digits <- someParser
return $ someFunction digitssomeFunction <$> someParser-- | Parses a number at a specific base
parseNumberBase :: Char -> Parser LispVal
parseNumberBase 'b' = Number . fromJust . readBinary <$> many1 (oneOf "01")
parseNumberBase 'o' = Number . fst . head . readOct <$> many1 octDigit -- see below
parseNumberBase 'd' = Number . read <$> many1 digit
parseNumberBase 'h' = Number . fst . head . readHex <$> many1 hexDigit -- see below
parseNumberBase _ = error "Wrong number base"parseBinary :: Parser LispVal
parseBinary = Number . fromJust . readBinary <$> many1 (oneOf "01")
parseDecimal :: Parser LispVal
parseDecimal = Number . read <$> many1 digit
parseHexadecimal :: Parser LispVal
parseHexadecimal = Number . fst . head . readHex <$> many1 hexDigit
parseOct :: Parser LispVal
parseOct = Number . fst . head . readOct <$> many1 octDigitparseNumber :: Parser LispVal
parseNumber = parseDecimal <|> char '#' *> parseNumberBase
parseNumberBase :: Parser LispVal
parseNumberBase = char 'h' *> parseHexadecimal
<|> char 'd' *> parseDecimal
<|> char 'o' *> parseOct
<|> char 'b' *> parseBinaryContext
StackExchange Code Review Q#118397, answer score: 2
Revisions (0)
No revisions yet.