Reputation: 35
This portion of code should read in two or more numbers (main io function omitted), then a "+" to give the sum. Rationals are used because later i will do multiplications and such other operations.
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)
The (second) error is with the parse function unable to handle
*Main> parse ["1","2","+"] [Number 3]
*** Exception: Prelude.read: no parse
I have looked on the Data.Ratio page and on the web for this solution but haven't found it and would appreciate some help. Thanks,
CSJC
Upvotes: 3
Views: 3390
Reputation: 183873
The first equation,
parse ("+":s)(a:b:xs) = parse (s)((solve (Add (Number a) (Number b))):xs)
should be
parse ("+":s)(a:b:xs) = parse (s)((solve (Add a b)):xs)
since per the type signature, a
and b
already are Expression
s.
Or, in line with the second and third equations, change the type to
parse :: [String] -> [Rational] -> Double
and change the first equation to
parse ("+":s)(a:b:xs) = parse s ((a + b):xs)
Two possible ways of fixing the code (there were more problematic parts):
-- 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
The latter is rather circumspect, since in the end a Double
is produced, there's no real point using Rational
s for the stack.
In your code for parse
, the third equation leaves out the conversion of a Rational
to an Expression
via the Number
constructor, but is otherwise fine. The second equation, however, contains a different type of problem:
parse [] (answer:xs) = fromRational (toRational (read (show answer)::Float))
If answer
is either an Expression
or a Rational
, show answer
cannot be parsed as a Float
, so that will lead to a runtime error, as exemplified by your edit:
The (second) error is with the parse function unable to handle
*Main> parse ["1","2","+"] [Number 3]
*** Exception: Prelude.read: no parse
At the point where the second equation is used, the first element (answer
) on the stack is Number (3 % 1)
, and show (Number (3 % 1))
is "Number (3 % 1)"
, which is not a String
that read
can parse as a Float
.
Upvotes: 2