[英]Combining fragments of Haskell Code to get the bigger picture
這是我在某個地方遇到的代碼,但想知道它是如何工作的:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))
Output: findIndices (== 0) [1,2,0,3,0]
== [2,4]
,其中pred
是(==0)
& xs
是[1,2,0,3,0]
我將展示我的一些理解:
(zip [0..] xs)
上面這行所做的是將索引放入列表中的所有內容。 對於上面給出的輸入,它看起來像這樣: [(0,1),(1,2),(2,0),(3,3),(4,0)]
。
(pred . snd)
我發現這意味着類似pred (snd (x))
。 我的問題是, x
是由zip
線組成的列表嗎? 我傾向於是的,但我的猜測是站不住腳的。
接下來是我對fst
和snd
的理解。 我知道
fst(1,2) = 1
和
snd(1,2) = 2
這兩個命令在代碼中如何有意義?
我對filter
的理解是它返回一個匹配條件的項目列表。 例如,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
會給[6,7,8,9,10]
我對 map 的理解是,它將 function 應用於列表中的每個項目。 例如,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
會給[4,8,12,16,20]
這總體上如何運作? 我想我到目前為止所知道的已經很全面了,但不能把這些部分放在一起。 有人可以幫幫我嗎?
我發現這意味着類似
pred (snd (x))
。 我的問題是,x 是由 zip 線組成的列表嗎? 我傾向於是的,但我的猜測是站不住腳的。
pred. snd
pred. snd
,表示\x -> pred (snd x)
。 所以這基本上構造了一個 function ,它將元素x
映射到pred (snd x)
。
因此,這意味着表達式看起來像:
filter (\x -> pred (snd x)) (zip [0..] xs)
因此,這里x
是由zip
生成的 2 元組。 所以為了知道(0, 1)
, (1,2)
, (2, 0)
等是否保留在結果中, snd x
將取這些 2 元組的第二個元素(所以1
, 2
, 0
等),並檢查是否滿足 tha 元素的pred
。 如果滿足,它將保留該元素,否則該元素(2元組)將被過濾掉。
因此,如果(== 0)
是謂詞,則 filter ( pred
filter (pred. snd) (zip [0..] xs)
將包含 2 元組[(2, 0), (4, 0)]
。
但現在結果是一個 2 元組列表。 如果我們想要索引,我們需要以某種方式擺脫 2 元組以及這些 2 元組的第二個元素。 我們為此使用fst:: (a, b) -> a
:這將 2 元組映射到其第一個元素。 因此,對於列表[(2, 0), (4, 0)]
, map fst [(2, 0), (4, 0)]
將返回[2, 4]
。
在 Haskell 我們想說,遵循 types 。 實際上,這些部分就像通過從類型到相應類型的電線連接一樣:
(一、 function組成為:
(f >>> g) x = (g . f) x = g (f x)
(f >>> g) = (g . f) = \x -> g (f x)
而function組合類型推斷規則為:
f :: a -> b -- x :: a
g :: b -> c -- f x :: b
------------------------- -- g (f x) :: c
f >>> g :: a -> c
g . f :: a -> c
現在, )
findIndices :: (b -> Bool) -> [b] -> [Int]
findIndices pred = \xs -> map fst ( filter (pred . snd) ( zip [0..] xs ))
= map fst . filter (pred . snd) . zip [0..]
= zip [0..] >>> filter (snd >>> pred) >>> map fst
---------------------------------------------------------------------------
zip :: [a] -> [b] -> [(a, b)]
zip [0..] :: [b] -> [(Int,b)]
---------------------------------------------------------------------------
snd :: (a,b) -> b
pred :: b -> Bool
------------------------------------
(snd >>> pred) :: (a,b) -> Bool
---------------------------------------------------------------------------
filter :: (t -> Bool) -> [t] -> [t]
filter (snd >>> pred) :: [(a,b)] -> [(a,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
---------------------------------------------------------------------------
fst :: (a, b) -> a
map :: (t -> s) -> [t] -> [s]
map fst :: [(a,b)] -> [a]
map fst :: [(Int,b)] -> [Int]
所以,總的來說,
zip [0..] :: [b] -> [(Int,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
map fst :: [(Int,b)] -> [Int]
---------------------------------------------------------------------------
findIndices pred :: [b] -> [Int]
你問過,這些部分是如何組合在一起的?
就是這樣。
使用列表推導,您的 function 寫為
findIndices pred xs = [ i | (i,x) <- zip [0..] xs, pred x ]
在偽代碼中顯示:
“結果列表包含zip [0..] xs
中每個 ( i
(i,x)
的 i,這樣pred x
成立” 。
它通過轉動n
-long 來做到這一點
xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]
進入
[0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]
其中[a | True]
[a | True]
是[a]
和[a | False]
[a | False]
是[]
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.