私は Haskell を学んでいますが、Haskell Wikiの次の式に は本当に戸惑いました。
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
なぜこれが機能するのか、私にはよくわかりません。
標準のカリー化ロジックを適用する(zipWith (+))
と、引数としてリストを受け取る関数が返され、別のリストを引数として受け取る別の関数が返され、リスト ( zipWith::(a -> b -> c) -> [a] -> [b] -> [c]
) が返されます。したがって、fibs
は (まだ評価されていない) リストへの参照(tail fibs)
であり、同じ (未評価の) リストの末尾です。( ) を評価しようとするとtake 10 fibs
、最初の 2 つの要素が と にバインドされ0
ます1
。つまりfibs==[0,1,?,?...]
、 と(tail fibs)==[1,?,?,?]
. 最初の追加が完了すると、 にfibs
なり[0,1,0+1,?,..]
ます。同様に、2 番目の加算の後、次のようになります。[0,1,0+1,1+(0+1),?,?..]
- 私の論理は正しいですか?
- これを説明する簡単な方法はありますか?(Haskell コンパイラがこのコードで何をするかを知っている人からの洞察はありますか?) (リンクと参照は大歓迎です)
- このタイプのコードは、遅延評価のためにのみ機能するというのは本当ですか?
- を行うと、どのような評価が行われます
fibs !! 4
か? - このコードは、zipWith が要素を最初から最後まで処理することを前提としていますか? (そうすべきではないと思いますが、理由がわかりません)
EDIT2:上記の質問があり、ここでよく答えられていることがわかりました。誰かの時間を無駄にしてしまい申し訳ありません。
編集: これは理解するのがより難しいケースです (ソース: Project Euler forums ):
filterAbort :: (a -> Bool) -> [a] -> [a]
filterAbort p (x:xs) = if p x then x : filterAbort p xs else []
main :: Int
main = primelist !! 10000
where primelist = 2 : 3 : 5 : [ x | x <- [7..], odd x, all (\y -> x `mod` y /= 0) (filterAbort (<= (ceiling (sqrt (fromIntegral x)))) primelist) ]
ここでall (\y -> x mod y /= 0)...
x を参照しても無限再帰が発生しないことに注意してください。