阅读"真实世界Haskell",第95页,作者提供了一个例子:
myFoldl f z xs = foldr step id xs z
where step x g a = g (f a x)
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么这段代码会编译?foldr只需要三个参数-但在这里,它是通过四:step,id,xs,z.
例如,这不起作用(因为总和需要一个):
sum filter odd [1,2,3]
Run Code Online (Sandbox Code Playgroud)
相反,我必须写:
sum $ filter odd [1,2,3]
Run Code Online (Sandbox Code Playgroud)
Mat*_*ick 12
这是以下类型foldr:
Prelude> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
Run Code Online (Sandbox Code Playgroud)
我们能弄清楚它是如何成为一个四参数函数的吗?试一试吧!
我们将它id :: d -> d作为第二个参数(b),所以让我们将其替换为类型:
(a -> (d -> d) -> (d -> d)) -> (d -> d) -> [a] -> (d -> d)
Run Code Online (Sandbox Code Playgroud)在Haskell中,a -> a -> a它是相同的a -> (a -> a),它给了我们(删除最后一组括号):
(a -> (d -> d) -> (d -> d)) -> (d -> d) -> [a] -> d -> d
Run Code Online (Sandbox Code Playgroud)让我们简化,通过置换e为(a -> (d -> d) -> (d -> d))与f对(d -> d),使之更易于阅读:
e -> f -> [a] -> d -> d
Run Code Online (Sandbox Code Playgroud)所以我们可以清楚地看到我们已经构建了一个四参数函数!我头疼.
这是一个从n-arg函数创建n + 1参数函数的简单示例:
Prelude> :t id
id :: a -> a
Run Code Online (Sandbox Code Playgroud)
id 是一个参数的函数.
Prelude> id id id id id 5
5
Run Code Online (Sandbox Code Playgroud)
但我刚给它5个args!
Dan*_*ner 10
这是因为多态性foldr是多少:
foldr :: (a -> b -> b) -> b -> [a] -> b
Run Code Online (Sandbox Code Playgroud)
在这里,我们已经实例化为b一个函数类型,让我们调用它c -> c,所以foldr专门的类型(例如)
foldr :: (a -> (c -> c) -> (c -> c)) -> (c -> c) -> [a] -> c -> c
Run Code Online (Sandbox Code Playgroud)
foldr只需要3个参数
错误.Haskell中的所有函数都只取1个参数,并产生恰好1个结果.
foldr :: (a -> b -> b) -> b -> [a] -> b
Run Code Online (Sandbox Code Playgroud)
看,foldr拿一个参数(a -> b -> b),产生1个结果:b -> [a] -> b.当你看到这个:
foldr step id xs z
Run Code Online (Sandbox Code Playgroud)
请记住,这只是简写:
((((foldr step) id) xs) z)
Run Code Online (Sandbox Code Playgroud)
这解释了为什么这是无稽之谈:
sum filter odd [1,2,3]
(((sum filter) odd) [1,2,3])
Run Code Online (Sandbox Code Playgroud)
sum :: Num a => [a] -> a 将列表作为输入,但您给它一个函数.