5

私はlearnyouahaskell.comを読んでいて、現在折り目を調査しています。この本には、次のような例があります。

maximum' :: (Ord a) => [a] -> a  
maximum' = foldr1 (\x acc -> if x > acc then x else acc)  

reverse' :: [a] -> [a]  
reverse' = foldl (\acc x -> x : acc) []  

product' :: (Num a) => [a] -> a  
product' = foldr1 (*)  

filter' :: (a -> Bool) -> [a] -> [a]  
filter' p = foldr (\x acc -> if p x then x : acc else acc) []  

head' :: [a] -> a  
head' = foldr1 (\x _ -> x)  

last' :: [a] -> a  
last' = foldl1 (\_ x -> x) 

head'とを除くすべてを理解していますtail'

バイナリ関数をアキュムレータとリスト内の各要素に順番に適用し、すべてのリストを処理する必要があることを理解しています。なぜこれは頭(または尾)で止まるのですか?

_(アンダースコア)が「何でも」または「気にしない」を意味することは理解していますが、それがすべてのリストを通過するのをどのように停止しますか?

4

2 に答える 2

6

foldr1firstの定義を見てみましょう。

foldr1 :: (a -> a -> a) -> [a]       -> a
foldr1    f                [x]       =  x
foldr1    f                (x : xs)  =  f x (foldr1 f xs)

head'次に、関数の呼び出しを検討してください。

head' :: [a] -> a  
head' =  foldr1 (\x _ -> x)

リストに、次のように言います[2, 3, 5]:

head' [2, 3, 5]

さて、 の右辺を埋めるとhead'

foldr1 (\x _ -> x) [2, 3, 5]

[2, 3, 5]のシンタックス シュガーであることを思い出してください(2 : 3 : 5 : [])。したがって、 の定義の 2 番目のケースがfoldr1適用され、結果が得られます。

(\x _ -> x) 2 (foldr1 (\x _ -> x) (3 : 5 : [])

現在、アプリケーションを減らすと、無視されたパラメーターにバインドされ、バインドさ2xます。残っているのは、ラムダ抽象化の右側を次のように置き換えたものです。foldr1 (\x _ -> x) (3 : 5 : [])_x2

2

遅延評価により、無視された引数foldr1 (\x _ -> x) (3 : 5 : [])が評価されないままになることに注意してください。これは、リストの残りの部分を処理する前に、再帰が停止することに注意してください。

于 2013-05-21T20:20:49.187 に答える