[英]Why isn't it necessary to provide a parameter in this function?
I'm fairly new to Haskell and this week I found this particular function in a couple of lecture slides. 我是Haskell的新手,本周我在几张幻灯片中找到了此特定功能。 I'm trying to understand why the following function doesn't need to include a parameter:
我试图了解为什么以下函数不需要包含参数:
-- Return all final segments of the argument, longest first
-- (horrible runtime complexity, used here for illustration purposes only)
tails :: [a] -> [[a]]
tails = reverse . map reverse . inits . reverse
If I would call it like tails "thisisastring"
then this would be a valid argument. 如果我将其称为
tails "thisisastring"
那么这将是一个有效的参数。 Isn't it necessary to provide a parameter, for example tails xs = ...
. 不必提供参数,例如
tails xs = ...
All the other functions I seen before were in that fashion. 我以前看到的所有其他功能都是这种方式。
This is called point-free style (where "point" is a mathematical term that basically means "argument" here). 这称为无点样式(其中“点”是一个数学术语,在这里基本上表示“自变量”)。
Even tails xs = ...
is just syntactic sugar for tails = \\xs -> ...
, so all you need to do to convince yourself that tails
is a function is to recognize that 即使是
tails xs = ...
也只是tails = \\xs -> ...
语法糖,因此,要使自己相信tails
是一个函数,您需要做的就是认识到
reverse
, map reverse
, and inits
are all functions: reverse
, map reverse
和inits
都是函数:
map
is a higher-order function; map
是一个高阶函数; it takes one function as an argument and returns another function. 它使用一个函数作为参数,然后返回另一个函数。
map reverse
is a function because map
is applied to the function reverse
. map reverse
是一个函数,因为将map
应用于reverse
函数。
Thus 从而
reverse . map reverse
reverse . map reverse
is a function, reverse . map reverse
功能 reverse . map reverse . inits
reverse . map reverse . inits
reverse . map reverse . inits
reverse . map reverse . inits
is a function, reverse . map reverse . inits
是一个功能, reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
is a function. reverse . map reverse . inits . reverse
是一种功能。 Since tails
is assigned the value of reverse . map reverse . inits . reverse
由于为
tails
分配了reverse . map reverse . inits . reverse
的值reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
, tails
itself is also a function. reverse . map reverse . inits . reverse
, tails
本身也是一个功能。
The parameter is implicit. 该参数是隐式的。 Or to put it differently,
reverse . map reverse . inits . reverse
或者换句话说,
reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
reverse . map reverse . inits . reverse
evaluates to a function of type [a] -> [[a]]
. reverse . map reverse . inits . reverse
求值为类型[a] -> [[a]]
的函数。
Consider a simpler example: 考虑一个更简单的示例:
double_impl x = x * 2
double = double_impl
The type of double
here is the same type as double_impl
, ie it takes one parameter of typeclass Num
: 在这里,
double
的类型与double_impl
相同,即,它采用double_impl
Num
一个参数:
main = do
print $ double_impl 5
print $ double 5
-- Out: 10
-- Out: 10
We can see that tails
is a function, by checking it's type. 通过检查其类型,我们可以看到
tails
是一个函数。
To compute its type, we begin by writing down the types of all the intermediate functions in the composition. 为了计算其类型,我们首先写下组合中所有中间函数的类型。 Note that we use new type variables for each ocurrence of a function.
注意,对于函数的每次出现,我们都使用新的类型变量。
reverse :: [a] -> [a]
inits :: [b] -> [[b]]
map :: (c -> d) -> [c] -> [d]
Now we have map reverse
has type [[e]] -> [[e]]
since we get c=d=[e]
for some type e
from comparing the expressions 现在我们得到
map reverse
类型为[[e]] -> [[e]]
因为通过比较表达式,对于某些类型e
我们得到c=d=[e]
reverse :: c -> d -- for some c and d
reverse :: [e] -> [e] -- for some e
Hence the last two intermediates have types 因此,最后两个中间体具有类型
map reverse :: [[e]] -> [[e]]
reverse :: [f] -> [f]
Now we start trying to match up types. 现在我们开始尝试匹配类型。 Let me emphasize first that obviously THESE ARE NOT REAL TYPES!
首先让我强调一下,这些显然不是真实类型! (sorry for the all caps, but I don't want anyone to miss that.)
(对不起,大写,但我不想让任何人错过。)
inits . reverse :: [a] -*- [a] = [b] -*> [[b]]
-- I'm using a -*- b -*> c to denote the type a -> c obtained by
-- composing a function of type a -> b with one of type b -> c.
-- The *s are to break the double dashes up,
-- so they aren't parsed as a comment.
-- Anyway, looking at this type, we see
-- we must have [a] = [b], so a = b
-- we can rewrite the type of inits . reverse as
inits . reverse :: [a] -> [[a]]
Then for the next composition: 然后进行下一个合成:
map reverse . inits . reverse :: [a] -*- [[a]] = [[e]] -*> [[e]]
-- again, we have [[a]] = [[e]], so e = a, and we have
map reverse . inits . reverse :: [a] -> [[a]]
Finally, we have 最后,我们有
reverse . map reverse . inits . reverse :: [a] -*- [[a]] = [f] -*> [f]
-- This time we have [[a]] = [f], so we must have f = [a], so the type
-- of the final composition is
tails = reverse . map reverse . inits . reverse :: [a] -> [[a]]
Since tails
has the type [a] -> [[a]]
, it must be a function that accepts a list of a
s as it's argument and returns a list of lists of a
s. 由于
tails
有型[a] -> [[a]]
,它必须接受列表的功能, a
S作为它的参数,返回的清单列表a
秒。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.