Haskell 多参数过滤函数
Haskell filter function with multiple parameters
我正在尝试学习 Haskell 并且想知道如何使用一个带有多个参数的函数来过滤给定的列表,将列表中的每个元素与其他不变的元素一起传递给该函数,以创建一个新列表。
我知道我可以这样做来使用 bool 函数来过滤列表:
newList = filter theFunction aList
但是当 theFunction 像这样接受其他参数时会发生什么:
theFunction -> elementOfAList -> Int -> Bool
我如何过滤列表中的每个元素,同时将另一个元素解析到函数中?任何帮助将不胜感激:)
编辑 -> 为了提供更多信息,如果我想要一个来自 [1..10] 的整数列表,它会通过一个接受两个整数的函数进行过滤,如果 returns true第一个较小,我该怎么做?
在这种情况下,您可以使用部分应用的谓词函数,如下所示
-- theFunction :: elementOfAList -> Int -> Bool -- "::" means, "is of type"
newList = filter (flip theFunction i) aList
因为
flip theFunction i x = theFunction x i
根据 flip
的定义,因此 flip theFunction
的类型为 Int -> elementOfAList -> Bool
:
flip :: (a -> b -> c ) -> b -> a -> c
theFunction :: a -> Int -> Bool
flip theFunction :: Int -> a -> Bool
flip theFunction (i :: Int) :: a -> Bool
其中 i
是在别处定义的某个 Int
值。 a
是一个类型变量,即它可以是任何类型,例如列表元素的类型(即对于列表 aList :: [a]
每个元素具有相同的类型,a
)。
例如,对于 theFunction x i = x < i
,您可以调用 filter (flip theFunction 5) aList
,在结果列表中保留 aList
中小于 5 的所有元素。通常这会写成filter (< 5) aList
,同operator sections(其中(< 5)
为一例,绝对等同于flip theFunction 5
)。
上面的过滤将使用相同的Int
值i
调用theFunction
每个元素x
列表 aList
。如果你想重新计算 Int
,它是用另一种模式(即高阶函数)完成的,
mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
假设您想将 theFunction
找到的所有元素保存在一个整数列表中。然后你可以这样做
theFunction :: elementOfAList -> Int -> Bool
foo :: Int -> [Int] -> [Int]
foo i xs = concat (snd (mapAccumL g i xs)) -- normally written as
-- concat $ snd $ mapAccumL g i xs -- or
-- concat . snd $ mapAccumL g i xs -- or even
-- concat . snd . mapAccumL g i $ xs
where
g acc x -- g :: (acc -> x -> (acc, y)) according to mapAccumL's signature
| theFunction x acc = (x, [x]) -- include `x` in output, and update the acc
| otherwise = (acc, []) -- keep the accumulated value, and skip this `x`
因为 x
和 acc
都用于相同的角色(元组的第一个元素)它们必须是相同的类型。
我正在尝试学习 Haskell 并且想知道如何使用一个带有多个参数的函数来过滤给定的列表,将列表中的每个元素与其他不变的元素一起传递给该函数,以创建一个新列表。
我知道我可以这样做来使用 bool 函数来过滤列表:
newList = filter theFunction aList
但是当 theFunction 像这样接受其他参数时会发生什么:
theFunction -> elementOfAList -> Int -> Bool
我如何过滤列表中的每个元素,同时将另一个元素解析到函数中?任何帮助将不胜感激:)
编辑 -> 为了提供更多信息,如果我想要一个来自 [1..10] 的整数列表,它会通过一个接受两个整数的函数进行过滤,如果 returns true第一个较小,我该怎么做?
在这种情况下,您可以使用部分应用的谓词函数,如下所示
-- theFunction :: elementOfAList -> Int -> Bool -- "::" means, "is of type"
newList = filter (flip theFunction i) aList
因为
flip theFunction i x = theFunction x i
根据 flip
的定义,因此 flip theFunction
的类型为 Int -> elementOfAList -> Bool
:
flip :: (a -> b -> c ) -> b -> a -> c
theFunction :: a -> Int -> Bool
flip theFunction :: Int -> a -> Bool
flip theFunction (i :: Int) :: a -> Bool
其中 i
是在别处定义的某个 Int
值。 a
是一个类型变量,即它可以是任何类型,例如列表元素的类型(即对于列表 aList :: [a]
每个元素具有相同的类型,a
)。
例如,对于 theFunction x i = x < i
,您可以调用 filter (flip theFunction 5) aList
,在结果列表中保留 aList
中小于 5 的所有元素。通常这会写成filter (< 5) aList
,同operator sections(其中(< 5)
为一例,绝对等同于flip theFunction 5
)。
上面的过滤将使用相同的Int
值i
调用theFunction
每个元素x
列表 aList
。如果你想重新计算 Int
,它是用另一种模式(即高阶函数)完成的,
mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
假设您想将 theFunction
找到的所有元素保存在一个整数列表中。然后你可以这样做
theFunction :: elementOfAList -> Int -> Bool
foo :: Int -> [Int] -> [Int]
foo i xs = concat (snd (mapAccumL g i xs)) -- normally written as
-- concat $ snd $ mapAccumL g i xs -- or
-- concat . snd $ mapAccumL g i xs -- or even
-- concat . snd . mapAccumL g i $ xs
where
g acc x -- g :: (acc -> x -> (acc, y)) according to mapAccumL's signature
| theFunction x acc = (x, [x]) -- include `x` in output, and update the acc
| otherwise = (acc, []) -- keep the accumulated value, and skip this `x`
因为 x
和 acc
都用于相同的角色(元组的第一个元素)它们必须是相同的类型。