在 haskell 的新函数中使用过滤列表
Using a filtered list in a new function in haskell
所以我不太确定如何正确表达这个,但是说我想得到列表中所有奇数的总和,我有两个函数(sumList 和 getOddNumbers)并将它们组合成 sumOddList 还是有没有办法将这两个放在一个函数中?如果没有更好的功能,我该如何将它们组合成sumOddList?
getOddNumbers :: [Integer] -> [Integer]
getOddNumbers [] = []
getOddNumbers (x:xs)
|odd x = x:getOddNumbers xs
|otherwise = getOddNumbers xs
sumList :: [Integer] -> Integer
sumList list = case list of
[] -> 0
(x:xs) -> x + (sumList xs)
我之所以问,主要是因为将两个 diff 函数放在一起是我以前在使用 CodeWorld 放置颜色和形状以输出该颜色的形状时遇到的问题。
谢谢
(注意:我已经使用 Haskell 超过 5 个星期了,我显然是个菜鸟)
下面是函数oddSum :: [Integer] -> Integer
的三种等价写法:
oddSum xs = sumList (getOddNumbers xs)
oddSum xs = sumList $ getOddNumbers xs
oddSum = sumList . getOddNumbers
顺便说一句,看看 Prelude 中的 filter
和 sum
函数,您可以用它们分别替换 getOddNumbers
和 sumList
。
将输出作为输入传递给(另一个)函数
你基本上想要做的是使用getOddNumbers
的输出作为输入 用于 sumList
函数,所以我们可以定义一个 sumOddList
函数为:
sumOddList :: [Integer] -> Integer
sumOddList l = sumList (getOddNumbers l)
这里 l
是我们要处理的列表,因此结果是对 getOddNumbers l
的结果的函数应用(使用 sumList
函数)。
链接函数:(.)
函数
上述模式很常见:我们经常希望先通过函数 g
传递数据,然后通过函数 f
传递结果。 Haskell 具有 (.) :: (b -> c) -> (a -> b) -> a -> c
功能到 "chain" 功能。因此,我们可以将 sumList
和 getOddNumbers
链接在一起,例如:
sumOddList :: [Integer] -> Integer
sumOddList = (.) sumList getOddNumbers
请注意,我们在这里不再使用 l
参数。 sumOddList
在这里定义为 "pipeline",其中数据首先传递给 getOddNumbers
,然后由 sumList
函数传递 "post-processed"。
(.)
函数也可以用作中缀运算符:
sumOddList :: [Integer] -> Integer
sumOddList = sumList . getOddNumbers
or is there a way to put these two together in a single function ... sumOddList
?
是的。
通过使用一个人的输出作为另一个人的输入来链接函数,特别是在惰性评估下,但让我们依赖于编译器执行的融合。毕竟不能保证会发生(而且通常不会发生)。
相反,你说的 :
mapping f cons x xs = cons (f x) xs
filtering p cons x xs = if (p x) then (cons x xs) else xs
transduce xf cons z xs = foldr (xf cons) z xs
sumOddList xs = transduce (filtering odd) (+) 0 xs
因此,
> sumOddList [1..10]
25
> sum [1,3..10]
25
> transduce (mapping (+1) . filtering odd) (+) 0 [1..10]
35
> sum . filter odd . map (+1) $ [1..10]
35
> sum . map (+1) . filter odd $ [1..10]
30
> transduce (filtering odd . mapping (+1)) (+) 0 [1..10]
30
这是可行的,因为 folds fuse 通过组合它们的 reducer 函数的转换器(比如上面的 mapping
和 filtering
正在转换它们的 reducer 参数 cons
):
foldr (+) 0
. foldr (\x r -> x+1 : r) []
. foldr (\x r -> if odd x then x : r else r) []
$ [1..10]
=
foldr (+) 0
. foldr ((\cons x r -> cons (x+1) r) (:)) []
. foldr ((\cons x r -> if odd x then cons x r else r) (:)) []
$ [1..10]
=
foldr ((\cons x r -> cons (x+1) r) (+)) 0
. foldr ((\cons x r -> if odd x then cons x r else r) (:)) []
$ [1..10]
=
foldr ((\cons x r -> if odd x then cons x r else r)
((\cons x r -> cons (x+1) r) (+))) 0
$ [1..10]
=
foldr ( ( (\cons x r -> if odd x then cons x r else r)
. (\cons x r -> cons (x+1) r) ) (+)) 0
$ [1..10]
=
foldr ( (filtering odd . mapping (+1)) (+)) 0
$ [1..10]
=
foldr ( filtering odd ( mapping (+1) (+))) 0
$ [1..10]
=
30
一个foldr
做三个的工作。 Fusion 显式实现,通过在cons
操作从它们中抽象出来之后组合reducer函数,每个这样改变的函数成为一个cons
转换器,因此,容易与其他此类 cons
转换函数 组合。
所以我不太确定如何正确表达这个,但是说我想得到列表中所有奇数的总和,我有两个函数(sumList 和 getOddNumbers)并将它们组合成 sumOddList 还是有没有办法将这两个放在一个函数中?如果没有更好的功能,我该如何将它们组合成sumOddList?
getOddNumbers :: [Integer] -> [Integer]
getOddNumbers [] = []
getOddNumbers (x:xs)
|odd x = x:getOddNumbers xs
|otherwise = getOddNumbers xs
sumList :: [Integer] -> Integer
sumList list = case list of
[] -> 0
(x:xs) -> x + (sumList xs)
我之所以问,主要是因为将两个 diff 函数放在一起是我以前在使用 CodeWorld 放置颜色和形状以输出该颜色的形状时遇到的问题。
谢谢
(注意:我已经使用 Haskell 超过 5 个星期了,我显然是个菜鸟)
下面是函数oddSum :: [Integer] -> Integer
的三种等价写法:
oddSum xs = sumList (getOddNumbers xs)
oddSum xs = sumList $ getOddNumbers xs
oddSum = sumList . getOddNumbers
顺便说一句,看看 Prelude 中的 filter
和 sum
函数,您可以用它们分别替换 getOddNumbers
和 sumList
。
将输出作为输入传递给(另一个)函数
你基本上想要做的是使用getOddNumbers
的输出作为输入 用于 sumList
函数,所以我们可以定义一个 sumOddList
函数为:
sumOddList :: [Integer] -> Integer
sumOddList l = sumList (getOddNumbers l)
这里 l
是我们要处理的列表,因此结果是对 getOddNumbers l
的结果的函数应用(使用 sumList
函数)。
链接函数:(.)
函数
上述模式很常见:我们经常希望先通过函数 g
传递数据,然后通过函数 f
传递结果。 Haskell 具有 (.) :: (b -> c) -> (a -> b) -> a -> c
功能到 "chain" 功能。因此,我们可以将 sumList
和 getOddNumbers
链接在一起,例如:
sumOddList :: [Integer] -> Integer
sumOddList = (.) sumList getOddNumbers
请注意,我们在这里不再使用 l
参数。 sumOddList
在这里定义为 "pipeline",其中数据首先传递给 getOddNumbers
,然后由 sumList
函数传递 "post-processed"。
(.)
函数也可以用作中缀运算符:
sumOddList :: [Integer] -> Integer
sumOddList = sumList . getOddNumbers
or is there a way to put these two together in a single function ...
sumOddList
?
是的。
通过使用一个人的输出作为另一个人的输入来链接函数,特别是在惰性评估下,但让我们依赖于编译器执行的融合。毕竟不能保证会发生(而且通常不会发生)。
相反,你说的 :
mapping f cons x xs = cons (f x) xs
filtering p cons x xs = if (p x) then (cons x xs) else xs
transduce xf cons z xs = foldr (xf cons) z xs
sumOddList xs = transduce (filtering odd) (+) 0 xs
因此,
> sumOddList [1..10]
25
> sum [1,3..10]
25
> transduce (mapping (+1) . filtering odd) (+) 0 [1..10]
35
> sum . filter odd . map (+1) $ [1..10]
35
> sum . map (+1) . filter odd $ [1..10]
30
> transduce (filtering odd . mapping (+1)) (+) 0 [1..10]
30
这是可行的,因为 folds fuse 通过组合它们的 reducer 函数的转换器(比如上面的 mapping
和 filtering
正在转换它们的 reducer 参数 cons
):
foldr (+) 0
. foldr (\x r -> x+1 : r) []
. foldr (\x r -> if odd x then x : r else r) []
$ [1..10]
=
foldr (+) 0
. foldr ((\cons x r -> cons (x+1) r) (:)) []
. foldr ((\cons x r -> if odd x then cons x r else r) (:)) []
$ [1..10]
=
foldr ((\cons x r -> cons (x+1) r) (+)) 0
. foldr ((\cons x r -> if odd x then cons x r else r) (:)) []
$ [1..10]
=
foldr ((\cons x r -> if odd x then cons x r else r)
((\cons x r -> cons (x+1) r) (+))) 0
$ [1..10]
=
foldr ( ( (\cons x r -> if odd x then cons x r else r)
. (\cons x r -> cons (x+1) r) ) (+)) 0
$ [1..10]
=
foldr ( (filtering odd . mapping (+1)) (+)) 0
$ [1..10]
=
foldr ( filtering odd ( mapping (+1) (+))) 0
$ [1..10]
=
30
一个foldr
做三个的工作。 Fusion 显式实现,通过在cons
操作从它们中抽象出来之后组合reducer函数,每个这样改变的函数成为一个cons
转换器,因此,容易与其他此类 cons
转换函数 组合。