3

コードのこの部分は、2 つ以上の数値 (メインの io 関数は省略) を読み取り、次に "+" を使用して合計を計算する必要があります。後で乗算やその他の操作を行うため、有理数が使用されます。

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)

(2番目の)エラーは、解析関数が処理できないことです

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

*** Exception: Prelude.read: no parse

私は Data.Ratio ページと Web でこのソリューションを探しましたが、見つかりませんでした。助けていただければ幸いです。ありがとう、

CSJC

4

1 に答える 1

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すでにExpressions です。

または、2 番目と 3 番目の式に従って、タイプを次のように変更します。

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

最初の方程式を次のように変更します

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

コードを修正する 2 つの方法が考えられます (さらに問題のある部分がありました)。

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

後者はかなり慎重です。最終的に aDoubleが生成されRational、スタックに s を使用する意味がないからです。

のコードでは、3 番目の式はコンストラクターを介したaから anへparseの変換を省略していますが、それ以外は問題ありません。ただし、2 番目の式には別のタイプの問題が含まれています。RationalExpressionNumber

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

がまたは のanswerいずれかである場合、として解析できないため、編集で例示されているように、実行時エラーが発生します。ExpressionRationalshow answerFloat

(2番目の)エラーは、解析関数が処理できないことです

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

2 番目の式が使用される時点でanswer、スタックの最初の要素 ( ) はNumber (3 % 1)でありshow (Number (3 % 1))、であり、として解析できるで"Number (3 % 1)"はありません。StringreadFloat

于 2012-04-26T17:44:16.147 に答える