将谓词添加到地图功能

Lea*_*nan 3 haskell filtering map

完全是Haskell的新手,通过Learn Haskell学习更大的好处.

我正在看地图功能

map :: (a -> b) -> [a] -> [b]  
map _ [] = []  
map f (x:xs) = f x : map f xs  
Run Code Online (Sandbox Code Playgroud)

是否可以为此添加谓词?例如,仅映射到列表中的每个其他元素?

chi*_*chi 7

您可以将自己的版本编码mapf仅应用于偶数(或奇数)位置,如下所示.(指数从下方开始0)

mapEven :: (a->a) -> [a] -> [a]
mapEven f []     = []
mapEven f (x:xs) = f x : mapOdd f xs

mapOdd :: (a->a) -> [a] -> [a]
mapOdd f []     = []
mapOdd f (x:xs) = x : mapEven f xs
Run Code Online (Sandbox Code Playgroud)

如果你想要利用库函数,你可以做类似的事情

mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (\(flag,x) -> if flag then f x else x) . zip (cycle [True,False])
Run Code Online (Sandbox Code Playgroud)

甚至

mapEven :: (a->a) -> [a] -> [a]
mapEven f = map (uncurry (\flag -> if flag then f else id)) . zip (cycle [True,False])
Run Code Online (Sandbox Code Playgroud)

如果要使用索引上的任意谓词进行过滤,则:

mapPred :: (Int -> Bool) -> (a->a) -> [a] -> [a]
mapPred p f = map (\(i,x) -> if p i then f x else x) . zip [0..]
Run Code Online (Sandbox Code Playgroud)

使用zipWith(如@amalloy建议的)可以达到更直接的解决方案.

mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith (\flag x -> if flag then f x else x) (cycle [True,False])
Run Code Online (Sandbox Code Playgroud)

这可以进一步细化如下

mapEven :: (a->a) -> [a] -> [a]
mapEven f = zipWith ($) (cycle [f,id])
Run Code Online (Sandbox Code Playgroud)