合并 Haskell 代码片段以获得更大的画面
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))
输出: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
的理解是 returns 符合条件的项目列表。例如,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
会给[6,7,8,9,10]
我对 map 的理解是它对列表中的每个项目应用一个函数。例如,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
会给[4,8,12,16,20]
这总体上如何运作?我想到目前为止我所知道的已经很全面了,但还不能完全把各个部分拼凑起来。有人可以帮我吗?
I found that this means something like pred (snd (x))
. My question is, is x the list made from the zip line? I'm leaning towards yes but my guess is flimsy.
嗯pred . snd
,就是\x -> pred (snd x)
。所以这基本上构造了一个函数,将元素 x
映射到 pred (snd x)
.
这意味着表达式看起来像:
filter (<b>\x -> pred (snd x)</b>) (zip [0..] xs)
这里x
因此是由zip
生成的二元组。所以为了知道结果中是否保留了(0, 1)
、(1,2)
、(2, 0)
等,snd x
会取这些二元组的第二个元素(所以1
、2
、0
等),并检查元素上的 pred
是否满足。如果满足,则保留该元素,否则过滤掉该元素(二元组)。
所以如果 (== 0)
是 pred
icate,那么 filter (pred . snd) (zip [0..] xs)
将包含二元组 [(2, 0), (4, 0)]
.
但现在结果是一个二元组列表。如果我们想要索引,我们需要以某种方式摆脱二元组和这些二元组的第二个元素。为此,我们使用 fst :: (a, b) -> a
:这会在其第一个元素上映射一个二元组。因此对于列表 [(2, 0), (4, 0)]
,map fst [(2, 0), (4, 0)]
将 return [2, 4]
.
在Haskell中我们喜欢说,遵循类型。事实上,这些部分就像通过从类型到相应类型的电线连接一样:
( 首先,函数组成是:
(f >>> g) x = (g . f) x = g (f x)
(f >>> g) = (g . f) = \x -> g (f x)
和函数组合类型推断规则是:
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>[b]</b> -> <b>[(Int,b)]</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) :: <b>[(Int,b)]</b> -> <b>[(Int,b)]</b>
---------------------------------------------------------------------------
fst :: (a, b) -> a
map :: (t -> s) -> [t] -> [s]
map fst :: [(a,b)] -> [a]
map fst :: <b>[(Int,b)]</b> -> <b>[Int]</b>
总的来说,
zip [0..] :: <b>[b]</b> -> [(Int,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
map fst :: [(Int,b)] -> <b>[Int]</b>
---------------------------------------------------------------------------
findIndices pred :: <b>[b]</b> -> <b>[Int]</b>
你问过,这些碎片是如何组合在一起的?
就是这样。
使用 list comprehensions,你的函数写成
findIndices pred xs = [ i | (i,x) <- zip [0..] xs, pred x ]
伪代码为:
"result list contains i
for each (i,x)
in zip [0..] xs
such that pred x
holds"。
它通过将 n
-long
xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]
进入
[0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]
其中 [a | True]
是 [a]
,[a | False]
是 []
。
这是我在某处遇到的代码,但想知道它是如何工作的:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))
输出: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
的理解是 returns 符合条件的项目列表。例如,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
会给[6,7,8,9,10]
我对 map 的理解是它对列表中的每个项目应用一个函数。例如,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
会给[4,8,12,16,20]
这总体上如何运作?我想到目前为止我所知道的已经很全面了,但还不能完全把各个部分拼凑起来。有人可以帮我吗?
I found that this means something like
pred (snd (x))
. My question is, is x the list made from the zip line? I'm leaning towards yes but my guess is flimsy.
嗯pred . snd
,就是\x -> pred (snd x)
。所以这基本上构造了一个函数,将元素 x
映射到 pred (snd x)
.
这意味着表达式看起来像:
filter (<b>\x -> pred (snd x)</b>) (zip [0..] xs)
这里x
因此是由zip
生成的二元组。所以为了知道结果中是否保留了(0, 1)
、(1,2)
、(2, 0)
等,snd x
会取这些二元组的第二个元素(所以1
、2
、0
等),并检查元素上的 pred
是否满足。如果满足,则保留该元素,否则过滤掉该元素(二元组)。
所以如果 (== 0)
是 pred
icate,那么 filter (pred . snd) (zip [0..] xs)
将包含二元组 [(2, 0), (4, 0)]
.
但现在结果是一个二元组列表。如果我们想要索引,我们需要以某种方式摆脱二元组和这些二元组的第二个元素。为此,我们使用 fst :: (a, b) -> a
:这会在其第一个元素上映射一个二元组。因此对于列表 [(2, 0), (4, 0)]
,map fst [(2, 0), (4, 0)]
将 return [2, 4]
.
在Haskell中我们喜欢说,遵循类型。事实上,这些部分就像通过从类型到相应类型的电线连接一样:
( 首先,函数组成是:
(f >>> g) x = (g . f) x = g (f x)
(f >>> g) = (g . f) = \x -> g (f x)
和函数组合类型推断规则是:
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>[b]</b> -> <b>[(Int,b)]</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) :: <b>[(Int,b)]</b> -> <b>[(Int,b)]</b>
---------------------------------------------------------------------------
fst :: (a, b) -> a
map :: (t -> s) -> [t] -> [s]
map fst :: [(a,b)] -> [a]
map fst :: <b>[(Int,b)]</b> -> <b>[Int]</b>
总的来说,
zip [0..] :: <b>[b]</b> -> [(Int,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
map fst :: [(Int,b)] -> <b>[Int]</b>
---------------------------------------------------------------------------
findIndices pred :: <b>[b]</b> -> <b>[Int]</b>
你问过,这些碎片是如何组合在一起的?
就是这样。
使用 list comprehensions,你的函数写成
findIndices pred xs = [ i | (i,x) <- zip [0..] xs, pred x ]
伪代码为:
"result list contains i
for each (i,x)
in zip [0..] xs
such that pred x
holds"。
它通过将 n
-long
xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]
进入
[0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]
其中 [a | True]
是 [a]
,[a | False]
是 []
。