[英]Use foldr to define map in Haskell,
我是Haskell的新手,並嘗試了解map函數。
到目前為止,我了解以下內容。
map::(a->b)->[a]->[b]
map f (x:xs) = f x : map f xs
但我不理解以下定義:使用文件夾定義地圖
map'::(a->b)->[a]->[b]
map' f = foldr ( (:).f ) []
誰能解釋以上地圖的定義以及為什么與地圖相同
讓我們看看foldr
的來源 :
foldr k z = go where
go [] = z
go (x:xs) = k x (go xs)
現在,讓我們將map
的定義與go
的定義進行比較:
map f [] = []
map f (x:xs) = f x : map f xs
看起來很相似,不是嗎? 讓我們重寫第二個子句,以提取將x
與遞歸調用的結果結合在一起的部分:
map f [] = []
map f (x:xs) = (\v vs -> f v : vs) x (map f xs)
現在的相似之處非常清楚。 我們甚至可以寫一些名稱來使並行化更明確:
map f [] = z where z = []
map f (x:xs) = k x (map f xs) where k = \v vs -> f v : vs
只需替換go
在上面看到map f
任何地方,您就會看到定義是相同的! 因此,本着DRY的精神,我們可以嘗試將foldr
重復用於以上內容:
map f = foldr (\v vs -> f v : vs) []
這使您對如何從map
到文件foldr
。 一直到給出的定義只是一些語法技巧。 現在,我們將重點介紹foldr
的function參數:
\v vs -> f v : vs
= { writing the infix operator prefix instead }
\v vs -> (:) (f v) vs
= { eta reduction }
\v -> (:) (f v)
= { definition of function composition }
\v -> ((:) . f) v
= { eta reduction }
(:) . f
因此,使用這種推理鏈,我們可以得出最終形式
map f = foldr ((:) . f) []
替代答案,希望某些人可以使用。
foldr fz xs
替換每:
在xs
與f
,並[]
與z
。 所以
a : b : c : d : []
變成
a `f` b `f` c `f` d `f` z
現在,讓我們從map'
的定義中替換值。
a `(:).f` b `(:).f` c `(:).f` d `(:).f` []
(我在擴展Haskell語法)。
現在,
a `(:).f` as
是相同的
(:) (f a) as
這與
f a : as
繼續這種轉變,我們得到
f a : f b : f c : f d : []
嘿,這看起來像是將直線map f
應用於[a,b,c,d]
,不是嗎?
首先你需要了解
foldr (:) []
另一個只是在缺點之前應用函數f
,因此等效於map
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.