我试图改变以下列表理解:
f xs = [ x+8 | (x,_) <- xs ]
使用高阶函数。
我的第一个解决方案是:
f' xs = map (\(x,_) -> x+8) xs
在我尝试了其他各种方法之后,我发现以下内容也有效:
f' xs = map((+8).fst) xs
f'
的两个版本都提供相同(正确)的输出,但在使用(+8).fst
时,我不明白为什么\(x,_) -> x+8
等于map
元组列表。
答案 0 :(得分:7)
fst
的定义是
fst :: (a, b) -> a
fst (a, _) = a
并且(.)
的定义是
(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) = \x -> f (g x)
如果我们使用这些定义来扩展您的功能,我们会得到
f' xs = map ((+8) . fst) xs
f' xs = map (\x -> (+8) (fst x)) xs -- definition of (.)
f' xs = map (\x -> (+8) ((\(a, _) -> a) x)) -- definition of fst
f' xs = map (\(a, _) -> (+8) a) -- we can move the pattern matching
f' xs = map (\(a, _) -> a + 8) -- expand section
答案 1 :(得分:4)
两种版本的f&#39;给出相同(正确)的输出,但在元组列表中使用map时,我不明白为什么
(+8).fst
等于(x,_) -> x+8
。
fst
的类型是:
fst :: (a, b) -> a
它的作用是它需要一对中的第一个元素(两个元素的元组)。
(+8)
的类型是:
(+8) :: Num a => a -> a
它的作用是输入Num
,将+ 8
应用于它并返回结果。
现在,(+8) . fst
的类型是:
((+8).fst) :: Num c => (c, b) -> c
是fst
和(+8)
的组合。具体来说,它是将一对作为输入的函数,提取第一个元素并向其添加8
。
通过以下示例可以很容易地看出这一点:
((+8).fst) (3, 'a')
-- 11
同样的事情发生在\ (x, _) -> x + 8
上。你将一对作为输入(在lambda中),模式匹配x
的第一个参数,将其递增8
并返回它:
(\ (x, _) -> x + 8) (3, 'a')
-- 11