Yes. This might seem a little overpowered, but using a parser combinator library like Parsec would allow you to write the code neatly. E.g.
import Text.ParserCombinators.Parsec
import Data.Maybe
monom, term :: Parser Term
operations :: [(Char,(Term -> Term -> Term))] -> Parser Term
int :: Parser Int
int = fmap read $ many1 digit
monom = do
coef <- int
string "x^"
power <- int
return $ Monom coef power
operations ops = do
a <- term
c <- choice . map (char . fst) $ ops
b <- term
return $ (fromJust $ lookup c ops) a b
term = do
char '('
x <- monom <|> (operations [('+', Addition), ('-', Subtraction), ('*', Multiplication), ('/', Division)])
char ')'
return x
term' = do
x <- term
eof
return x
readTerm :: String -> Term
readTerm string = case parse term' "" string of
Left err -> error . show $ err
Right term -> term
As an explanation, monom
parses something like 2x^3
(without brackets), operations
takes a list of tuples and parses a term
followed by one of the operation characters, followed by another term
, and then uses the appropriate data constructor to make the right instance (the fromJust $ lookup c ops
line).
The term
parser parses either a monom
or one of the operations, surrounded by brackets. term'
parses a whole string (i.e. makes sure that the parser runs to the end of the string). readTerm
is just a "cleaner" version of the parser.
Some examples:
> readTerm "(2x^3)"
Monom 2 3
> readTerm "((2x^3)+(2x^3))"
Addition (Monom 2 3) (Monom 2 3)
> readTerm "(((2x^3)+(2x^3))*(2x^3))"
Multiplication (Addition (Monom 2 3) (Monom 2 3)) (Monom 2 3)
The above is a very basic version, and can easily be extended to (for example) make the coef
term optional, so that x^2
parses as Monom 1 2
, or make the power
term optional so that 2x
parses as Monom 2 1
. (The option
function is extremely useful for this specific modification, and only adds 1 or 2 more lines.)
(Note. this might be more efficient and elegant written in an applicative style, e.g.
import Control.Applicative
monom = Monom <$> int <* string "x^" <*> int
but this can get a bit unweildy when making modifications.)