[英]Haskell function for list length
要使用foldr計算列表的長度,可以執行以下操作:
foldr (\_ acc -> acc + 1) 0
進一步擴展折疊函數需要增加第二個參數的想法,我想出了這個(這是錯誤的):
foldr ((+1) . (flip const)) 0`
進一步檢查該類型揭示了這一點:
(+1) . (flip const) :: Num (c -> c) => a -> c -> c
Haskell高階函數計算長度在該頁面上有一個有趣的評論,我真的無法理解
foldr (((+1).).(flip const)) 0
有人可以解釋一下這個組合是如何運作的嗎?
首先,讓我們關注為什么foldr ((+1) . (flip const)) 0
是錯誤的。 您只想增加第二個參數而忘記第一個參數。 從語義上講,就是這樣
\_ a -> a + 1
但是,您寫了以下內容:
(+1) . flip const
= (+1) . (\_ a -> a)
= \x -> (+1) . (\_ a -> a) $ x
= \x -> (+1) $ (\_ a -> a) $ x
= \x -> (+1) $ \a -> a
= \_ -> (+1) (\a -> a)
= const ( (+1) (\a -> a))
這就是你突然需要Num (c -> c)
,因為你試圖在id
上申請(+1)
。
但你實際上意味着:
\_ a -> a + 1
= \_ a -> (+1) a
= \_ -> (+1)
= const (+1)
畢竟,你想忘記第一個參數並在第二個參數上使用函數f
。 你所const f
就是使用const f
。
組合((+1).).(flip const)
過於冗長,可能是由pointfree生成的:
((+1).).(flip const)
= ((\x -> x + 1).) . (\a _ -> a)
= \c -> ((\x -> x + 1).) . (\a _ -> a) $ c
= \c -> ((\x -> x + 1).) $ \_ -> c
= \c -> \f -> (\x -> x + 1) . f $ \_ -> c
= \c -> (\x -> x + 1) . \_ -> c
= \_ c -> (\x -> x + 1) $ c
= \_ c -> c + 1
這真的是一個評論,但對於一個人來說太長了。
除非你正在處理像懶人Nat
這樣奇怪的數字,否則你真的很想要
length xs = foldl' (\acc _ -> 1 + acc) 0 xs
使這毫無意義,
length = foldl' (\acc -> const ((1+) acc)) 0
length = foldl' (const . (1+)) 0
如果您願意,可以將原始的foldl'
表達式轉換為foldr
形式,如下所示:
length xs = foldr go id xs 0 where
go _ r acc = r $! 1 + acc
咀嚼go
,
go _ r acc = ($!) r $ (+) 1 acc
go _ r = ($!) r . (+1)
go _ r = (. (+1)) (($!) r)
go _ = (. (+1)) . ($!)
go = const ((. (+1)) . ($!))
咀嚼length
,
length = flip (foldr go id) 0
把它們放在一起,
length = flip (foldr (const ((. (+1)) . ($!))) id) 0
就我而言,我發現這種無點形式是完全不透明的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.