0

コードを ghci でコンパイルすると、問題はありません。正しくコンパイルできます。ただし、ハグでコンパイルしようとすると、「コンパイルされたコードが複雑すぎます」というエラーが表示されます。|問題は多くの条件によるものだと思います。

if/elseに変更すれば問題ありません。if/else ステートメントを 100 回追加できますが、これは非常に面倒で面倒です。それよりも、20 ~ 30 の条件の後に if/else ステートメントを配置しようとしましたが、次のような if ステートメント内では機能し|ません。|

f x y z     
    | cond1 = e1
    | cond2 = e2
    ...
    if (1)
    then
    | cond30 = e30
    | cond31 = e31
    ...
    else
    | cond61 = e61
    | cond62 = e62

最小限の労力でコードを修正するにはどうすればよいですか? StackOverflow の質問サイズ制限よりも長いため、完全なコードはhpasteにあります。

4

2 に答える 2

9

ガードの繰り返しを避ける

まず、書き直すことができます

function input 
   | this && that && third thing && something else = ...   -- you only actually needed brackets for (head xs) 
   | this && that && third thing && something different = ....
   | this && that && a change && ...  
...
   | notthis && ....

function input | this = function2 input'
               | notthis = function4 input'

function2 input | that = function3 input''
                | notthat = ...

これにより、200 行のコードが簡素化されるはずcopoですが、それでもまだ間違ったアプローチです。

関数を使用して、同じ問題を毎回ではなく 1 回だけ処理する

何度も処理する操作を処理するための 4 つのケースは、おそらく次のような 1 つの関数に置き換えることができます。

operation :: Num a => Char -> a -> a -> a
operation x = case x of
   '+' -> (+)
   '-' -> (-)
   '*' -> (*)
   '/' -> (/)
   _   -> error ("operation: expected an operation (+-*/) but got " ++ [c])

文字を 1 つずつテストする代わりにリスト関数を使用する

いくつかの標準関数を使用して、すべての単一文字チェックを減らして、存在する数だけを取得する必要があります。takeWhile :: (a -> Bool) -> [a] -> [a]、 それで

takeWhile isDigit "354*243" = "354"
takeWhile isDigit "+245" = ""

対応するものがありdropWhileます:

dropWhile isDigit "354*1111" = "*1111"
dropWhile isDigit "*1111" = "*1111"

したがって、コードの最も劇的な短縮は、copo を開始することです。

copo xs = let 
  numText = takeWhile isDigit xs
  theRest = droWhile isDigit xs 
  num = read numText
  ....
    in answer....

ただし、 と の両方が必要な場合は、 と呼ばれるショートカットがありtakeWhileますdropWhilespanspan p xs == (takeWhile p xs, dropWhile p xs)

copo xs = let 
  (numText,theRest) = span isDigit xs
  num = read numText
  ....
    in answer....

コードを繰り返す代わりに再帰を使用する

234あなたはそれ234*56から対処し234*56/23ます....

これを への再帰呼び出しに置き換えるcopoか、ツリーを作成することができます。これは、通常の演算子の優先順位 (+ または - の前に * または /) に従うかどうかによって異なります。

于 2013-04-06T13:00:26.880 に答える
0

代わりに警備員を主張する場合

foo a b c d
    | cond1, cond2, cond3 = ...
    | cond1, cond2, cond4 = ...
    | cond5, cond6, cond7 = ...
    | cond5, cond6, cond8 = ...

書きます

foo a b c d
    | cond1, cond2 = case () of
        () | cond3 = ...
           | cond4 = ...
    | cond5, cond6 = case () of
        () | cond7 = ...
           | cond8 = ...
于 2013-04-06T16:08:12.907 に答える