2012-04-26 70 views
3

這部分代碼應該讀取兩個或更多數字(省略主io函數),然後用「+」來給出總和。理性被使用,因爲後來我會做乘法和其他操作。***例外:Prelude.read:Haskell中不解析 - 解析,表達式和遞歸

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

+0

你的第二個錯誤是在我的答案已經處理:) – 2012-04-26 18:43:15

+0

是的,看來你已經搶佔這樣的事情,因爲我打字吧! – CSJC 2012-04-26 18:48:21

回答

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秒。

或者,在與第二和第三方程線,所述類型更改爲

parse :: [String] -> [Rational] -> Double 

和第一方程改變爲固定代碼的

parse ("+":s)(a:b:xs) = parse s ((a + b):xs) 

兩種可能的方法(有是更有問題的部分):

-- Complete solve to handle all cases 
solve :: Expression -> Expression 
solve [email protected](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代碼,第三個方程省去了通過Number構造一個RationalExpression的轉換,但在其他方面正常。第二個公式,但是,含有不同類型的問題:

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

如果answer或者是一個ExpressionRationalshow answer不能被解析爲一個Float,這樣將導致一個運行時間錯誤,通過所例示您編輯:

(第二)錯誤是用解析功能無法處理

*Main> parse ["1","2","+"] [Number 3] 
*** Exception: Prelude.read: no parse 

在其中使用所述第二方程點,堆疊在所述第一元件(answer)是Number (3 % 1),和show (Number (3 % 1))"Number (3 % 1)",其不是Stringread可以作爲一個Float解析。

+0

太好了,謝謝你澄清這一點。 – CSJC 2012-04-26 17:50:34

+0

這是否也適用於'solve(Add(Number x)(Number y))= Number(x + y)'可以是'solve(Add x y)= Number(x + y)'? – CSJC 2012-04-26 18:00:24

+0

編號在'Add x y'中,'x'和'y'是'Expression's,但Number'需要一個'Rational'參數,'(+)'沒有爲'Expression'定義。就解決方案而言,「解決」是正確的(當然,它是不完整的)。 – 2012-04-26 18:05:06