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))