18

たとえば、fnB :: a -> Boolreturn まで意味のない操作がありfnA :: BoolますFalse。CI では、次の 2 つの操作を 1 つのifブロックにまとめることができます。

if( fnA && fnB(a) ){ doSomething; }

Cは false を返すfnBまで実行しないことを保証します。fnA

seqしかし、Haskell は怠け者であり、通常、コードを厳密にするために 、$!、またはその他の何かを使用しない限り、どの操作が最初に実行されるかは保証されません。一般的に、これは私たちが幸せになるために必要なものです。しかし、演算子を使用すると、結果が返されるまで評価されないこと&&が予想されます。Haskell は でそのような保証を提供しますか? また、Haskellは Falseを返しても評価しますか?fnBfnA&&fnBfnA

4

4 に答える 4

34

この関数(&&)は、最初の引数が の場合にのみ、2 番目の引数が正格ですTrue。最初の引数では常に正格です。この厳密さ/怠惰さが評価の順序を保証するものです。

そのため、C とまったく同じように動作します。違いは、Haskell では、(&&)が通常の関数であることです。Cでは、これは不可能です。

しかし、Haskell は怠け者であり、一般に、コードを厳密にするために seq や $! などを使用しない限り、どの操作が最初に実行されるかは保証されません。

これは正しくありません。真実はもっと深い。

厳密な集中コース:

(&&)次の理由により、最初のパラメーターが厳密であることがわかっています。

⊥ && x = ⊥

ここで、⊥ はundefinedまたは無限ループのようなものです (⊥ は「底」と発音します)。(False &&)2 番目の引数が非正格であることもわかっています。

False && ⊥ = False

2 番目の引数が評価できない ⊥ であるため、2 番目の引数を評価できない可能性があります。ただし、次の(True &&)理由により、関数の 2 番目の引数は正格です。

True && ⊥ = ⊥

したがって、 は(&&)最初の引数では常に正格であり、2 番目の引数では最初の引数が の場合にのみ正格であると言えますTrue

評価の順序:

の場合(&&)、厳密性プロパティは実行順序を保証するのに十分です。いつもそうであるとは限りません。たとえば、(+) :: Int -> Int -> Intは両方の引数で常に正格であるため、どちらの引数を先に評価してもかまいません。ただし、IOモナドで例外をキャッチするか、unsafe関数を使用する場合にのみ、違いを見分けることができます。

于 2011-09-30T15:23:57.490 に答える
5

他の人が指摘したように、当然(&&)、その引数の 1 つは厳密です。標準的な定義では、最初の引数は正格です。flipセマンティクスを反転するために使用できます。

追加の注意として: への引数(&&)は副作用を持つことができないことに注意x && yしてyください。

  • パフォーマンス:y計算に時間がかかる場合。
  • セマンティクス: あなたがそれを期待するなら、y底になることができます.
于 2011-09-30T16:16:54.997 に答える
1

Haskell は遅延型であり、通常、どの操作が最初に実行されるかは保証されません。

そうではありません。Haskell は純粋(unsafePerformIOと の実装を除く) であり、どの操作が最初に実行されるかを観察するIO方法はありません(と の実装を除く)。実行の順序は結果にとって重要ではありませんunsafePerformIOIO

&&1 つまたは両方の引数が である場合を含む 9 つの値の真理値表がありundefined、操作を正確に定義します。

a           b           a && b
True        True        True
True        False       False
True        undefined   undefined
False       True        False
False       False       False
False       undefined   False
undefined   True        undefined
undefined   False       undefined
undefined   undefined   undefined

実装がその表に従っている限り、任意の順序で実行できます。

(表を調べてみると、最初に実行されない限り順次実装がそれに続く方法がないことに気付くでしょう。その場合、 iffは True です。しかし、Haskell 実装は順次である必要はありません!実装は常にキックすることができます必要なときにいつでも実行できます。唯一の保証は、表によると、実行の結果が Trueの場合にのみプログラムに影響を与えるということです)。ababba

(「怠惰」は、上記のような真理値表を持つ関数を記述する唯一の方法であることに注意してください。C や ML のような言語では、いずれかの引数に含まれる 5 行すべてが結果としてundefined強制されます。 undefinedHaskell (および C では&&、C 言語に組み込まれているため) では、行の 1 つがFalse代わりに結果として含まれる場合があります。)

于 2016-08-31T15:30:28.397 に答える
-1

期待どおりに機能すると思います。LHS が True と評価された場合、RHS を評価します。しかし、RHS に副作用がないと仮定すると、どのように知る (または気にする) のでしょうか?

編集: RHS は である可能性があると思いundefinedます。

于 2011-09-30T15:26:33.587 に答える