问题描述
这个问题很简单,但我似乎无法理解这个概念.
So this question is simple but I can't seem to grasp the concept.
要组成普通函数,只需执行以下操作即可:
To compose ordinary functions, one can just do something like below:
lowerNoSpaces = filter (/= ' ') . map toLower
但是,有时候,这有时行不通:
But, on occasion, there are times where this won't work:
myConcatMap = concat . map
它给出了错误:
<interactive>:236:1: error:
* Non type-variable argument
in the constraint: Foldable ((->) [a1])
(Use FlexibleContexts to permit this)
* When checking the inferred type
concattMap :: forall a1 a2.
Foldable ((->) [a1]) =>
(a1 -> a2) -> [a2]
但是当这样表达相同的功能时:
But when the same function is expressed like this:
myConcatMap = (concat .) . map
它完全按预期工作.
我知道这是有原因的,但是我盯着它看了一阵子,但仍然不太明白为什么原版不起作用而这个原本可以起作用.
I know there is a reason for this, but I have been staring at it for a while and still don't quite understand why the original doesn't work and this one does.
为什么有两个."的?
推荐答案
这很容易从(.)
的定义和Haskell语法知识中得出.
This is fairly easy to derive from the definition of (.)
and knowledge of Haskell syntax.
首先从更明确的myConcatMap
定义开始,该定义为
You start with a more explicit definition of myConcatMap
, which is
\f -> \xs -> concat (map f xs)
通过组合运算符的定义,您可以将其编写为
By definition of the composition operator, you can write this as
\f -> concat . (map f)
使用.
在前缀位置而不是作为中缀运算符来重写它.
Rewrite this using .
in prefix position rather than as an infix operator.
\f -> (.) concat (map f)
并添加一些多余的括号,因为函数应用是左关联的.
and add some redundant parentheses since function application is left-associative.
\f -> ((.) concat) (map f)
使用部分语法重写此代码,以使.
再次成为中缀运算符
Rewrite this using section syntax to make .
an infix operator again
\f -> (concat .) (map f)
并使用功能(concat .)
和map
再次应用(.)
的定义:
and apply the definition of (.)
one more time, using the functions (concat .)
and map
:
(concat .) . map
这篇关于为什么功能组合有时需要两个“".结合两个功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!