質問

無限リストで正しく動作するコードがいくつかありますが、なぜ正常に動作するかはわかりません。 (無限リストを処理しない元のコードを変更して、他のコードから何かをオンラインに組み込むと、突然動作することがわかりましたが、理由はわかりません)。

myAny :: (a -> Bool) -> [a] -> Bool
myAny p list = foldr step False list
   where
      step item acc = p item || acc

folderの私の理解は、リスト内のすべての項目をループすることです(そして、おそらく理解が不完全です)。その場合、「ステップ」がどのように問題にならないか関数が表現されています...コードは無限ループを処理できないはずです。

ただし、次のように機能します:

*Main Data.List> myAny even [1..]
True

理解を助けてください:なぜ??

役に立ちましたか?

解決

Haskellがあなたの表現をどのように評価するかについて、少しトレースしてみましょう。各行の等号を等号に置き換えると、式は非常に迅速にTrueと評価されます。

myAny even [1..]
foldr step False [1..]
step 1 (foldr step False [2..])
even 1 || (foldr step False [2..])
False  || (foldr step False [2..])
foldr step False [2..]
step 2 (foldr step False [3..])
even 2 || (foldr step False [3..])
True   || (foldr step false [3..])
True

これは、 acc が未評価のサンク(遅延評価)として渡されるため機能しますが、 || 関数は first 引数。

これで終了します:

True || and (repeat True)

しかし、これはそうではありません:

and (repeat True) || True

||の定義を見てくださいなぜそうなのかを見るには:

True  || _ =  True
False || x =  x

他のヒント

  

folderの私の理解は、   内のすべてのアイテムをループします   リスト(そしておそらくその理解   不完全です)。

folder は( foldl とは異なり)リストのすべての項目をループする必要はありません。 folder がどのように定義されているかを調べることは有益です。

foldr f z []     = z
foldr f z (x:xs) = f x (foldr f z xs)

folder の呼び出しが評価されると、関数 f の呼び出しの評価が強制されます。ただし、 folder の再帰呼び出しが、関数 f の引数にどのように埋め込まれるかに注意してください。 f が2番目の引数を評価しない場合、その再帰呼び出しは評価されません。

ここで重要なのは、Haskellが非厳密な言語であることです。 "非厳格な"は、厳密でない関数を許可することを意味します。つまり、関数パラメーターは、使用される前に完全に評価されない可能性があります。これにより、明らかに遅延評価が可能になります。これは、「結果が必要になるまで計算を遅らせる手法」です。

このWiki記事

から開始

私はHaskellを知りませんが、あなたの場合、遅延評価のために動作すると思われます。リストを無限に操作できるため、リストにアクセスすると、必要に応じて結果が計算されます。

http://en.wikipedia.org/wiki/Lazy_evaluation

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top