簡體   English   中英

Haskell函數用於列表長度

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM