私は Haskell を初めて使用し、WhereとLetで非常に混乱しています。どちらも同様の目的を提供しているようです。WhereとLetの比較をいくつか読んだことがありますが、それぞれをいつ使用するかを判断するのに苦労しています。誰かがコンテキストや、どちらを使用するかを示すいくつかの例を提供してもらえますか?
どことレット
where
句は、関数定義のレベルでのみ定義できます。通常、それはlet
定義の範囲と同じです。唯一の違いは、ガードが使用されている場合です。where
句の範囲は、すべてのガードに及びます。対照的に、let
式のスコープは、現在の関数句とガード (存在する場合) のみです。
Haskell Wikiは非常に詳細で、さまざまなケースを提供していますが、仮説的な例を使用しています。初心者には説明が短すぎると思います。
Let の利点:
f :: State s a
f = State $ \x -> y
where y = ... x ...
where は f = に一致するパターンを参照し、x が範囲内にないため、機能しません。対照的に、let で開始した場合は、問題はありません。
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
どこの利点:
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
f x
= let a = w x
in case () of
_ | cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
Haskell wiki では、 Where句は宣言的であり、Let式は表現的であると述べています。スタイルは別として、彼らはどのように異なるパフォーマンスを発揮しますか?
Declaration style | Expression-style
--------------------------------------+---------------------------------------------
where clause | let expression
arguments LHS: f x = x*x | Lambda abstraction: f = \x -> x*x
Pattern matching: f [] = 0 | case expression: f xs = case xs of [] -> 0
Guards: f [x] | x>0 = 'a' | if expression: f [x] = if x>0 then 'a' else ...
- 最初の例では、Letがスコープ内にあるのにWhereがそうでないのはなぜですか?
- 最初の例にWhereを適用することは可能ですか?
- 変数が実際の式を表す実際の例にこれを適用できる人はいますか?
- それぞれをいつ使用するかに従う一般的な経験則はありますか?
アップデート
後でこのスレッドにたどり着いた人のために、ここにある最良の説明を見つけました:「Haskellへの穏やかな紹介」。
式をしましょう。
Haskell の let 式は、ネストされたバインディングのセットが必要な場合に便利です。簡単な例として、次のことを考慮してください。
let y = a*b f x = (x+y)/y in f c + f d
let 式によって作成されたバインディングのセットは相互に再帰的であり、パターン バインディングは遅延パターンとして扱われます (つまり、暗黙の ~ を持ちます)。許可される宣言の種類は、型シグネチャ、関数バインディング、およびパターン バインディングのみです。
Where 条項。
where 句を必要とするいくつかの保護された方程式にバインディングのスコープを設定すると便利な場合があります。
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
これは、let 式では実行できないことに注意してください。let 式は、囲まれている式のみをスコープします。where 句は、一連の方程式またはケース式の最上位でのみ使用できます。let 式のバインディングに対する同じプロパティと制約が、where 句のバインディングにも適用されます。ネストされたスコープのこれら 2 つの形式は非常に似ているように見えますが、let 式は式であるのに対し、where 句はそうではないことに注意してください。これは、関数宣言とケース式の構文の一部です。