I recently started to learn Haskell in order to write some small tools for me. Currently I'm working on a program which calculates how much steam a (railcraft) boiler of a given size outputs per tick.
In the console the user inputs a string of the following format:
S | L | BL-Size | BH-Size, example BH-3x3x4
I then use ParserCombinators from the Text.ParserCombinators.ReadP library to parse this string into a custom type. However I think my parser is overly complicated. Any suggestions how to simplify the following code?
module Boilers (Boiler(..), Tank(..)) where data Boiler = Hobbyist | Locomotive | Boiler (Int, Int, Int) Tank deriving (Show) data Tank = HighPressure | LowPressure deriving (Eq, Show) module BoilerParser where import Data.Char import Text.ParserCombinators.ReadP import Control.Applicative import Boilers import Data.Maybe boiler :: ReadP Boiler boiler = do b <- standard <++ hobbyist <++ locomotive maybe pfail return b standard :: ReadP (Maybe Boiler) standard = do satisfy (\c -> toUpper c == 'B') t <- fmap (\t -> case toUpper t of 'H' -> Just HighPressure 'L' -> Just LowPressure _ -> Nothing) get satisfy (== '-') s <- BoilerParser.size case t of Nothing -> pfail (Just a) -> return (Just (Boiler s a)) hobbyist :: ReadP (Maybe Boiler) hobbyist = fmap (\c -> if toUpper c == 'H' then Just Hobbyist else Nothing) get locomotive :: ReadP (Maybe Boiler) locomotive = fmap (\c -> if toUpper c == 'L' then Just Locomotive else Nothing) get size :: ReadP (Int, Int, Int) size = do x <- size' 1 satisfy (== 'x') y <- size' 1 satisfy (== 'x') z <- size' 1 return (x,y,z) size':: Int -> ReadP Int size' ds = fmap read (count ds (satisfy isDigit))