我正在尝试学习Haskell,并想知道如何过滤给定列表,使用带有多个参数的函数,将列表中的每个元素与其他不变元素一起传递给函数,以创建新列表。
据我所知,我可以使用bool函数来过滤列表:
newList = filter theFunction aList
但是当theFunction采用其他参数时会发生什么:
theFunction -> elementOfAList -> Int -> Bool
然后如何过滤列表中的每个元素,同时在另一个元素中解析函数?任何帮助将不胜感激:)
编辑 - >为了提供更多信息,如果我想要一个[1..10]的整数列表,那么通过一个带两个整数的函数进行过滤,如果第一个整数较小则返回true,我怎么能这样做? / p>
答案 0 :(得分:1)
在这种情况下,您使用部分应用的谓词函数,如此
-- 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的所有元素。通常这只会写为{{ 1}},operator sections(其中filter (< 5) aList
是一个示例,绝对等同于(< 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
都用在同一个角色(元组的第一个元素)中,所以它们必须是相同的类型。