具有谓词的Haskell映射函数

时间:2011-02-12 19:29:17

标签: haskell functional-programming filter map

我觉得这应该是相当明显或容易的,但我无法得到它。我想要做的是将一个函数应用于列表(使用map),但仅在条件被保持时。想象一下,你只想划分偶数的数字:

map (`div` 2) (even) [1,2,3,4]

这将给出[1,1,3,2],因为只有偶数才能将函数应用于它们。显然这不起作用,但有没有办法让这项工作无需编写你可以给地图分离的单独功能?过滤器几乎就在那里,除了我还想保留条件不适用的元素,而不是将函数应用于它们。

由于

6 个答案:

答案 0 :(得分:10)

如果您不想定义单独的函数,请使用lambda。

map (\x -> if (even x) then (x `div` 2) else x) [1,2,3,4]

或者代替地图,列表理解,我认为更具可读性。

[if (even x) then (x `div` 2) else x | x <- [1,2,3,4]]

答案 1 :(得分:7)

mapIf p f = map (\x -> if p x then f x else x)

答案 2 :(得分:3)

除了PiotrLegnica的答案之外:通常,如果你声明一个辅助函数而不是使用lambda,它会更容易阅读。考虑一下:

map helper [1..4] where
  helper x | even x    = x `div` 2
           | otherwise = x

[1..4][1,2,3,4])的糖

如果您想要删除所有其他元素,请考虑使用filterfilter删除所有不满足谓词的元素:

filter even [1..4] -> [2,4]

因此,您可以构建map的管道并过滤或使用列表理解:

map (`div` 2) $ filter even [1..4]
[x `div` 2 | x <- [1..4], even x]

选择你最喜欢的任何东西。

答案 3 :(得分:2)

制作自己的帮助函数制作者:

ifP pred f x = 
    if pred x then f x
    else x

custom_f = ifP even f
map custom_f [..]

(警告:我现在无法访问编译器。我猜这可以正常工作......)

答案 4 :(得分:1)

我喜欢其他更通用的解决方案,但在您非常特殊的情况下,您可以使用

map (\x -> x `div` (2 - x `mod` 2)) [1..4]

答案 5 :(得分:0)

主要是取消现有的答案,但根据我对“可读”的偏见定义(我喜欢警卫而不是ifs,where超过let):

mapIf p f = map f'
    where f' x | p x = f x | otherwise = x

ghci说它可能有效

ghci> let mapIf p f = map f' where f' x | p x = f x | otherwise = x
ghci> mapIf even (+1) [1..10]
[1,3,3,5,5,7,7,9,9,11]