どうにかここまで整理。
module Main (main) where import Text.ParserCombinators.Parsec -- 数式の要素(四則演算の演算子と整数値) data Elem = Plus | Minus | Times | Divide | Value Integer -- 後置法(逆ポーランド)で格納された要素を計算する関数 calc :: [Elem] -> Integer calc es = calc' es [] where calc' :: [Elem] -> [Integer] -> Integer calc' [] [n] = n calc' ((Value n):es) ns = calc' es (n:ns) calc' (Plus:es) (n:m:ns) = calc' es ((m + n):ns) calc' (Minus:es) (n:m:ns) = calc' es ((m - n):ns) calc' (Times:es) (n:m:ns) = calc' es ((m * n):ns) calc' (Divide:es) (n:m:ns) = calc' es ((m `div` n):ns) -- 文字列(中置表記の数式)を解析して、後置法で要素をリストに格納するパーサ -- 至って素朴な実装 expression :: Parser [Elem] expression = do { many space; t <- term; ts <- many $ try terms; many space; return $ t ++ (concat ts) } where terms = do { many space; op <- plus <|> minus; many space; t <- term; return (t ++ op) } term = do { f <- factor; fs <- many $ try factors; return $ f ++ (concat fs) } factors = do { many space; op <- times <|> divide; many space; f <- factor; return (f ++ op) } factor = do { char '('; e <- expression; char ')'; return e } <|> value value = do { v <- many digit; return [Value $ read v] } plus = do { char '+'; return [Plus] } minus = do { char '-'; return [Minus] } times = do { char '*'; return [Times] } divide = do { char '/'; return [Divide] } -- 一行ずつ文字列(数式)を読み込み、計算する main = do exps <- getContents mapM_ eval $ lines exps where eval exp = case (parse expression "" exp) of Right exp -> print $ calc exp Left err -> print err