我对Haskell相当新,本周我在几个演讲幻灯片中找到了这个特殊的功能。我试图理解为什么以下函数不需要包含参数:
-- 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
如果我将其称为tails "thisisastring"
,那么这将是一个有效的论点。是否有必要提供参数,例如tails xs = ...
。我之前见过的所有其他功能都是那种方式。
答案 0 :(得分:4)
这称为无点样式(其中“点”是一个数学术语,在这里基本上意味着“参数”)。
即使tails xs = ...
只是tails = \xs -> ...
的语法糖,所以你需要做的就是让自己说服tails
是一个函数就是认识到
reverse
,map reverse
和inits
都是功能:
map
是一个高阶函数;它将一个函数作为参数并返回另一个函数。
map reverse
是一个函数,因为map
已应用于函数reverse
。
因此
reverse . map reverse
是一个函数,reverse . map reverse . inits
是一个函数,reverse . map reverse . inits . reverse
是一个函数。由于tails
的值为reverse . map reverse . inits . reverse
,tails
本身也是一个函数。
答案 1 :(得分:3)
该参数是隐式的。或者换句话说,[a] -> [[a]]
评估为double_impl x = x * 2
double = double_impl
类型的函数。
考虑一个更简单的例子:
double
此处double_impl
的类型与Num
的类型相同,即它需要一个类型main = do
print $ double_impl 5
print $ double 5
-- Out: 10
-- Out: 10
的参数:
$('#yourTextBoxId').live('change keyup paste', function(){
if ($('#yourTextBoxId').val().length > 11) {
$('#yourTextBoxId').val($('#yourTextBoxId').val().substr(0,10));
}
});
答案 2 :(得分:2)
我们可以看到tails
是一个函数,通过检查它的类型。
要计算其类型,我们首先写下合成中所有中间函数的类型。请注意,我们为函数的每个事件使用新的类型变量。
reverse :: [a] -> [a]
inits :: [b] -> [[b]]
map :: (c -> d) -> [c] -> [d]
现在我们map reverse
的类型为[[e]] -> [[e]]
,因为我们通过比较表达式{/ 1>获得某些类型c=d=[e]
的{{1}}
e
因此最后两个中间体具有类型
reverse :: c -> d -- for some c and d
reverse :: [e] -> [e] -- for some e
现在我们开始尝试匹配类型。首先我要强调,显然这些并不是真正的类型! (对不起,所有的上限,但我不希望任何人错过。)
map reverse :: [[e]] -> [[e]]
reverse :: [f] -> [f]
然后是下一个作文:
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]]
最后,我们有
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]]
由于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]]
的类型为tails
,因此它必须是一个接受[a] -> [[a]]
列表作为其参数的函数,并返回a
个列表的列表