Haskell中的双重映射?

19

我仍然是Haskell的初学者。我能在Haskell中进行双重映射吗?

例如,如果我有一个[[Char]],我想将每个[Char]中的每个Char转换为小写,是否有一种简单的方法可以做到这一点,而不是像下面这样:

exampleF [] = []
exampleF (x:xs) = (map toLower x) : exampleF xs

我:“@faq Haskell能做双重映射吗?” Lambdabot:“答案是:可以!Haskell可以做到!” :) - Dan Burton
值得注意的是,map本身在Prelude中“尾递归”定义,与此片段具有相同的结构...基本上你甚至不知道自己已经实现了map! ;)就Haskell语义而言,你的方法和被接受的答案“做”的事情是一样的(我认为完全一样),只是写法不同。然而,说“map map”绝对更优雅。 - parker.sikand
2个回答

29

事实上,这里有一个很好的模式:

map           :: (a -> b) ->   [a]   ->   [b]
(map.map)     :: (a -> b) ->  [[a]]  ->  [[b]]
(map.map.map) :: (a -> b) -> [[[a]]] -> [[[b]]]

等等,诸如此类


1
更一般的说:(fmap . fmap) :: (Functor m, Functor n) => ( a -> b ) -> m (n a) -> m (n b) - Alexey Birukov

25

你可以将 map f 看作是将一个函数 f :: a -> b 转换成列表上的函数 map f :: [a] -> [b],所以如果你想将其进一步转换为列表的列表上的函数,则只需要再次使用 map 即可得到 map (map f) :: [[a]] -> [[b]]

在这个特定的例子中,变成了:

exampleF = map (map toLower)

5
exampleF xss = map (\xs -> map toLower xs) xss 的另一种写法是 exampleF xss = map (map toLower) xss。不过,我们鼓励使用 hammar 写的方式(因为它是 eta-reduced 和 point-free 的)。如果您还没有习惯这种写法,那么您会逐渐习惯的。 - Dan Burton
@DanBurton 请详细说明:为什么点无是更好的? - Refael Sheinker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接