第一个方程,
parse ("+":s)(a:b:xs) = parse (s)((solve (Add (Number a) (Number b))):xs)
应该
parse ("+":s)(a:b:xs) = parse (s)((solve (Add a b)):xs)
因为根据类型签名,a
并且b
已经是Expression
s。
或者,根据第二个和第三个等式,将类型更改为
parse :: [String] -> [Rational] -> Double
并将第一个方程更改为
parse ("+":s)(a:b:xs) = parse s ((a + b):xs)
修复代码的两种可能方法(有更多有问题的部分):
-- Complete solve to handle all cases
solve :: Expression -> Expression
solve expr@(Number _) = expr
solve (Add (Number x) (Number y)) = Number (x + y)
solve (Add x y) = solve (Add (solve x) (solve y))
-- Convert an Expression to Double
toDouble :: Expression -> Double
toDouble (Number x) = fromRational x
toDouble e = toDouble (solve e)
-- parse using a stack of `Expression`s
parse :: [String] -> [Expression] -> Double
parse ("+":s) (a:b:xs) = parse s ((solve (Add a b)):xs)
parse [] (answer:_) = toDouble answer
parse (x:xs) ys = parse xs (Number (toRational (read x :: Double)) : ys)
parse _ _ = 0
-- parse using a stack of `Rational`s
parseR :: [String] -> [Rational] -> Double
parseR ("+":s) (a:b:xs) = parseR s (a+b : xs)
parseR [] (answer:xs) = fromRational answer
parseR (x:xs) y = parseR xs ((toRational (read x::Double)):y)
parseR _ _ = 0
后者相当谨慎,因为最终产生了 a ,因此将s 用于堆栈Double
没有任何意义。Rational
在您的代码中parse
,第三个等式省略了通过构造函数将 a 转换为 aRational
的Expression
过程Number
,但其他方面都很好。然而,第二个等式包含不同类型的问题:
parse [] (answer:xs) = fromRational (toRational (read (show answer)::Float))
如果answer
是 anExpression
或 a Rational
,show answer
则不能解析为 a Float
,因此将导致运行时错误,如您的编辑所示:
(第二个)错误是解析函数无法处理
*Main> parse ["1","2","+"] [Number 3]
*** Exception: Prelude.read: no parse
在使用第二个等式的地方,answer
堆栈上的第一个元素 ( ) 是Number (3 % 1)
,并且show (Number (3 % 1))
是"Number (3 % 1)"
,它不是String
可以read
解析为 a 的 a Float
。