Haskell新手程序:计算逆波兰表达式

计算逆波兰表达式的值是Haskell教材《Learn you a haskell》第十章的题目
关于逆波兰表达式,可以参考维基百科逆波兰表示法词条

不看教程试一下自己实现foldingFunction,最终结果变成了这样
(不考虑任何异常处理)

import Data.List

data Operator = Add | Sub | Mul | Div

main = do
    exp <- getLine
    putStrLn $ show (solveRPN exp)

solveRPN :: String -> Float
solveRPN exp = head (foldl foldingFunction [] $ words exp)

foldingFunction :: [Float] -> String -> [Float]
foldingFunction stack item
    | item == "+" = calculate stack Add
    | item == "-" = calculate stack Sub
    | item == "*" = calculate stack Mul
    | item == "/" = calculate stack Div
    | otherwise = (read item) : stack

calculate :: (Fractional a) => [a] -> Operator -> [a]
calculate stack ope =
    let num1 = stack !! 1
        num2 = stack !! 0
        num = case ope of Add -> (num1 + num2)
                          Sub -> (num1 - num2)
                          Mul -> (num1 * num2)
                          Div -> (num1 / num2)
        result = num : (tail $ tail stack)
    in result

如果只考虑四则运算,教程的实现是

solveRPN :: String -> Float  
solveRPN = head . foldl foldingFunction [] . words  
    where   foldingFunction (x:y:ys) "*" = (x * y):ys
            foldingFunction (x:y:ys) "+" = (x + y):ys
            foldingFunction (x:y:ys) "-" = (y - x):ys
            foldingFunction (x:y:ys) "/" = (y / x):ys
            foldingFunction xs numberString = read numberString:xs

余的实现的几个缺点
1.代码又长又臭,完全没有发挥Haskell模式匹配的威力
2.为了代码复用,结果又加多了一个函数原型几乎和foldingFunction一样的calculate函数,多此一举
3.自定义的数据类型Operator也是多此一举 (从命令式编程还没转过来)
4.calculate的实现为二元运算,当需要扩展到一元运算(如对数运算ln)时,需要重写

本文目前尚无任何评论.

发表评论

XHTML: 您可以使用这些标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
:wink: :-| :-x :twisted: :) 8-O :( :roll: :-P :oops: :-o :mrgreen: :lol: :idea: :-D :evil: :cry: 8) :arrow: :-? :?: :!: