7

いくつかのパターンで計算を行う関数があるとしましょう。パターンマッチングの形で実装されています。

これらのパターンのほとんどは (それぞれに異なる他のことと共に)、let式で中間変数を使用するパラメーターの処理を行います。しかし、多くのパターンで同じものを使用するのは本当に冗長だと思います。いくつかのパターンに対してletを定義する方法があるのだろうか?let

これが私の重複した例ですlet

data MyType a = Something a | Another Int [a]

myFunc (Something x) = -- return something, this isn't the point here
myFunc (Another 0 xs) =
    let intermediary = some $ treatment xs
    in doSthg intermediary 1 
myFunc (Another 1 (x:xs)) =
    let intermediary = some $ treatment xs
    in doSthg1 intermediary 1 x
myFunc (Another 2 (x:x':xs)) =
    let intermediary = some $ treatment xs
    in doSthg2 intermediary 2 x x'

パラメータを に使用すると、パラメータxsが常に存在するintermediaryことがわかります。これは因数分解できます。ヘルパー関数を使用することで簡単に実現できますが、私が求めていることはヘルパー関数なしで可能かどうか疑問に思っていました. 初心者向けにシンプルにしてください。私の例が十分に明確であることを願っています。

4

1 に答える 1

7

この特定の問題は、次のように回避できます。

myFunc2 (Something x) = returnSomething x
myFunc2 (Another n ys) = 
    let xs = drop n ys
        x = head ys 
        x' = head (tail ys)
        intermediate = some $ treatment xs 
    in case n of
        0 -> doSomething intermediate n
        1 -> doSomething1 intermediate n x
        2 -> doSomething2 intermediate n x x'

x遅延評価のおかげでx'、それらの値が必要な場合にのみ評価されます。

しかし-そしてこれは大きなことです!myFunc2 (Another 2 [])-呼び出しようとすると(doSomething2実際に!を使用する場合) 、コードでランタイムエラーが発生します。これは、x何であるかを確認するためxに評価する必要があるためですhead ys-空のリストの場合はクラッシュします。Another 2 []例として示したコードも、一致するパターンがないため機能しません(別のランタイムエラー)が、フォールバックケースを提供する方が簡単です。

Another入力を制御し、のリストが十分な長さであることを常に確認する場合、これは問題にならない可能性がありますが、この問題に注意することが重要です。

于 2013-03-14T21:13:21.537 に答える