第一个参数,fmap
是预期的,是一个带有一个参数的函数。
fmap :: Functor f => (a -> b) -> f a -> f b
然后我尝试了前奏:
Prelude> x = fmap (\x y -> x * y)
如您所见,fmap
的第一个参数是一个函数,它有两个参数。为什么编译器允许它通过?
我传递给上面fmap
的函数有两个参数而不是一个!
答案 0 :(得分:9)
Haskell实际上没有比一个参数更多(或更少)的函数。 “双参数函数”实际上只是一个函数,它接受一个参数并产生另一个带另一个参数的函数。也就是说,\x y -> x * y
只是\x -> \y -> x * y
的句法捷径。这个概念被称为currying。
所以这应该解释你的例子中发生了什么。您的fmap
只会将f
个数字转换为f
个函数。因此,例如,x [1,2,3]
会生成列表[\y -> 1 * y, \y -> 2 * y, \y -> 3 * y]
(a.k.a。[(1*), (2*), (3*)]
)。
答案 1 :(得分:2)
您已定义了一项功能。函数式编程的一个基本方面是函数可以是参数,存储到变量等等。
如果我们然后查询x
的类型,我们会得到:
Prelude> :t x
x :: (Functor f, Num a) => f a -> f (a -> a)
所以x
现在是一个函数,它将 Functor
作为输入,a
应用于该函数,并返回一个类型的元素同一个仿函数,但应用了a -> a
。
因此,您可以在x
上应用列表,例如:
Prelude> :t x [1,4,2,5]
x [1,4,2,5] :: Num a => [a -> a]
现在我们有一个函数列表,等效于:
[\x -> 1*x, \x -> 4*x, \x -> 2*x, \x -> 5*x]