假设b是一个字符串列表并考虑,
map (map (\a -> ((head a), (length a))) . group . sort) (transpose b)
我知道上面的每个函数都做了什么,但我很难看到结果的组合方式。我该如何计算出这条线上的函数的运行顺序,以及哪些参数?
具体来说,我似乎明白(map (\a -> ((head a), (length a))) . group . sort)
是外部地图的第一个参数,(transpose b)
是外部地图的第二个参数。
但是哪个是内部地图的参数?内部地图似乎只有一个参数:(\a -> ((head a), (length a))) . group . sort)
。第二个参数(要应用的列表,元素方面,第一个参数中的函数)在哪里?
答案 0 :(得分:2)
您注意到的内容称为currying,它是Haskell功能的众多优秀(或可能不是)方面之一。这是你的代码:
map (map (\a -> ((head a), (length a))) . group . sort) (transpose b)
让我们检查第一个map
的类型:
map (\a -> ((head a), (length a))) :: [[a]] -> [(a, Int)]
我们这样做是通过输入
来实现的:t map (\a -> ((head a), (length a)))
进入 ghci 。
所以知道我们知道这是一个功能。它需要[[a]]
类型的元素并返回[(a, Int)]
。给地图函数的类型是
map :: (a -> b) -> [a] -> [b]
这很好。我们已经给了map
它的第一个参数,现在,它所需要的只是一个正确的列表。地图发生的事情称为currying。
现在让我们看看,我们有map
"已连接"通过sort
函数发送到group
和(.)
。
(.) :: (b -> c) -> (a -> b) -> a -> c
现在让我们改变你的一些代码,这样我们就可以更好地看到组合函数的用途。
map (\a -> ((head a), (length a))) . (group . sort)
我刚刚将group
和sort
与一些括号分开。但现在我们清楚地看到哪些元素充当了外(.)
的参数。
我们有相关的地图,以及另一个由其他构图产生的功能。当我们省略最后一个参数时,我们再次使用 currying :
map (\a -> ((head a), (length a))) . (group . sort)
:: Ord a => [a] -> [(a, Int)]
最后,外部map
从上方获取功能,并使用列表(transpose b)
。
答案 1 :(得分:1)
隐式地给出 。如果你写:
map (\a -> ((head a), (length a))) . group . sort
这实际上是简称:
\b -> (map (\a -> ((head a), (length a))) . group . sort) b
相当于:
\b -> map (\a -> ((head a), (length a))) $ group $ sort b
或:
\b -> map (\a -> ((head a), (length a))) (group (sort b))
(.) :: (b -> c) -> (a -> b) -> a -> c
运算符因此在某种管道中组合了两个函数:
(.) f g x = f (g x)
因为我们在这里写了三个用点分隔的函数:
map (\a -> ((head a), (length a))) . group . sort
-- \_________________ ______________/ \_ _/ \_ /
-- v v v
-- f g h
我们已经定义了某种类型的管道,其中元素首先通过h
进行处理,然后通过g
处理结果,最后通过f
处理结果。
答案 2 :(得分:1)
点本身就是一个函数,定义如下:
(f . g) x = f (g x)
让我们在外部地图的第一个参数中使用这个等式:
map (\a -> (head a, length a)) . group . sort
= { definition of (.), with map (\a -> ...) as f and group . sort as g }
\x -> map (\a -> (head a, length a)) ((group . sort) x)
因此,map (\a -> ...) . group . sort
是一个函数,当应用于参数x
时,会将(group . sort) x
作为参数提供给map (\a -> ...)
。