Haskell 示例中的函数组合
Function composition in Haskell example
假设 b 是字符串列表并考虑,
map (map (\a -> ((head a), (length a))) . group . sort) (transpose b)
我知道上面每个函数的作用,但我看不出结果是如何组合的。我将如何着手确定此行 运行 上的函数使用哪些参数的顺序?
具体来说,我好像明白了,(map (\a -> ((head a), (length a))) . group . sort)
是传给outer map的第一个参数,(transpose b)
是传给outer map的第二个参数。
但是内部地图的参数是什么?内部映射似乎只有一个参数:(\a -> ((head a), (length a))) . group . sort)
。第二个参数在哪里(要应用的列表,元素方面,第一个参数中的函数)?
它是隐式给出的。如果你写:
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
处理结果,最后通过 [=19= 处理结果].
点本身就是一个函数,定义如下:
(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 -> ...)
。
您注意到的是 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]]
和 returns [(a, Int)]
类型的元素。给出map函数的类型是
map :: (a -> b) -> [a] -> [b]
这很好。我们已经给了 map
它的第一个参数,现在,它所需要的只是一个合适的列表。 map 刚刚发生的事情叫做 currying.
现在让我们看看,我们通过 (.)
函数将 map
"connected" 转换为 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)
。
假设 b 是字符串列表并考虑,
map (map (\a -> ((head a), (length a))) . group . sort) (transpose b)
我知道上面每个函数的作用,但我看不出结果是如何组合的。我将如何着手确定此行 运行 上的函数使用哪些参数的顺序?
具体来说,我好像明白了,(map (\a -> ((head a), (length a))) . group . sort)
是传给outer map的第一个参数,(transpose b)
是传给outer map的第二个参数。
但是内部地图的参数是什么?内部映射似乎只有一个参数:(\a -> ((head a), (length a))) . group . sort)
。第二个参数在哪里(要应用的列表,元素方面,第一个参数中的函数)?
它是隐式给出的。如果你写:
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
处理结果,最后通过 [=19= 处理结果].
点本身就是一个函数,定义如下:
(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 -> ...)
。
您注意到的是 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]]
和 returns [(a, Int)]
类型的元素。给出map函数的类型是
map :: (a -> b) -> [a] -> [b]
这很好。我们已经给了 map
它的第一个参数,现在,它所需要的只是一个合适的列表。 map 刚刚发生的事情叫做 currying.
现在让我们看看,我们通过 (.)
函数将 map
"connected" 转换为 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)
。