web-dev-qa-db-ja.com

`let 5 = 10`は何をしますか?代入演算ではありませんか?

私が言うならlet 5 = 10、 なぜ 5 + 1 return 6 の代わりに 11

39
user2763173

あなたが言う時

let 5 = 10

これは5の再定義ではなく、パターンマッチングであり、あなたが言うときに同じことが起こります。

foo 5 = undefined
 ... foo 10 ...

一致した場合、パターンは単に失敗します。

Let-expressionsでは、一致は怠惰です。これは、一致がバインドされている変数が評価されたときにのみ一致が行われることを意味します。これにより、次のようなものを書くことができます

 let foo = undefined in 10

式では、変数がバインドされていないため、パターンが一致することはありません。

おそらく、変数のないこのようなパターンは、let-bindingsでは意味がなく、コンパイラーによって検出される必要がありますが、言語はそれらを禁止していません。

53

基本的に、

_let 5 = 10 in ...
_

と同等です

_case 10 of ~5 -> ...
_

lazyまたは反駁できないパターンをマークする_~_に注意してください。これはすべてに一致するパターンであり、実際に変数が要求されるポイントまで一致を延期します。パターン_5_には変数がないため、何も起こりません。

このコーナーケースはまったく役に立たないので、おそらくコンパイラはここで警告を発するはずです。

怠惰なパターンの意味を明確にするために、これを考慮してください:

_case f 3 of
  (x,y) -> g 10 x y
_

ここで、_f 3_が最初に(WHNFに対して)評価され、ペアコンストラクターが公開されます。次に、_x,y_が(まだ評価されていない)ペアコンポーネントにバインドされます。最後に、_g 10_が計算され、結果がx(現在要求される可能性があります)に適用され、次にyxまたはyが要求される可能性があります)に適用されます。

比較すると、

_case f 3 of
  ~(x,y) -> g 10 x y
_

_f 3_の評価から始まりません。代わりに、xは未評価のfst (f 3)にバインドされ、yは未評価のsnd (f 3)にバインドされます。代わりに、_g 10_の評価から始めます。次に、それをxに適用します。これにより、xが要求され、_f 3_の評価がトリガーされる可能性があります。次に、結果をyに適用して、同様の評価を行います。ほとんどの実装は実際にはsharexyの間の_f 3_の結果であるため、最大で1回計算されます。

17
chi

@ n.mとして。つまり、あなたはパターンマッチングです。下記は用例です。

パターンの一致は成功する可能性があります

Prelude> let (a, 10) = (15, 10) in a
15

または失敗します。

Prelude> let (a, 10) = (15, 15) in a
*** Exception: <interactive>:5:5-22: Irrefutable pattern failed for pattern (a, 10)

Haskellは怠惰なので、結果の値を使用しないとコードは成功します。これは本質的にあなたがしていることです:

Prelude> let (a, 10) = (15, 15) in "Something else"
"Something else"

タイプは引き続きチェックする必要があることに注意してください。

Prelude> let (a, 10, 999) = (15, 15) in "Something else"

<interactive>:7:20: error:
    • Couldn't match expected type ‘(t, Integer, Integer)’
                  with actual type ‘(Integer, Integer)’
    • In the expression: (15, 15)
      In a pattern binding: (a, 10, 999) = (15, 15)
      In the expression: let (a, 10, 999) = (15, 15) in "Something else"
    • Relevant bindings include a :: t (bound at <interactive>:7:6)
2
Teodor