***异常:Prelude.read:Haskell中没有解析 - 解析,表达式和递归

时间:2012-04-26 17:36:18

标签: parsing haskell expression

这部分代码应该读取两个或多个数字(省略主要功能),然后用“+”表示总和。使用Rationals是因为稍后我将进行乘法和其他操作。

data Expression =  Number Rational
               | Add (Expression)(Expression)
               deriving(Show,Eq)

solve :: Expression -> Expression
solve (Add (Number x) (Number y)) = Number (x + y)

parse :: [String] -> [Expression] -> Double
parse ("+":s)(a:b:xs) = parse s (solve (Add a b):xs)
parse [] (answer:xs) = fromRational (toRational (read (show answer)::Float))
parse (x:xs) (y) = parse (xs) ((Number (toRational (read x::Float))):y)

(第二个)错误是解析函数无法处理

*Main> parse ["1","2","+"] [Number 3]

*** Exception: Prelude.read: no parse

我已经在Data.Ratio页面和网络上查找了此解决方案,但尚未找到它并希望得到一些帮助。谢谢,

CSJC

1 个答案:

答案 0 :(得分:2)

第一个等式,

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)

因为根据类型签名,ab已经是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

后者是相当谨慎的,因为最终会产生Double,使用Rational来表示堆栈是没有意义的。

parse的代码中,第三个等式通过Rational构造函数省略了ExpressionNumber的转换,但在其他方面没有问题。然而,第二个等式包含不同类型的问题:

parse [] (answer:xs) = fromRational (toRational (read (show answer)::Float))

如果answerExpressionRational,则show answer无法解析为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可以解析为Float