You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

((->) a)的Applicative实例工作原理及<*>多参数定义解析

解析函数类型((->) a)的Applicative实例

让我一步步拆解这个问题,帮你搞清楚GHC.Base里定义的这个Applicative实例到底是怎么运作的,还有你疑惑的<*>参数问题~

先搞懂((->) a)是什么类型

首先,((->) a)是Haskell里的函数类型构造子,它是一个接受单个类型参数的构造子,对应我们平时写的a -> b(可以看成是((->) a) b的中缀写法)。因为Applicative要求构造子的kind是* -> *(也就是接受一个类型参数,返回一个具体类型),所以((->) a)完全符合要求——它接受类型b,返回具体的函数类型a -> b。

这个Applicative实例的运作逻辑

我们逐个看实例里的三个定义:

1. pure = const

先回忆Applicative中pure的类型:Applicative f => b -> f b。对于((->) a)来说,f b就是a -> b,所以pure的类型会被特化为b -> (a -> b)——也就是把一个值b转换成一个不管输入什么a类型参数,都返回这个b值的函数。

而const函数的类型正好是b -> a -> b,完全匹配这个需求!比如pure 5就等价于const 5,调用pure 5 "hello"或者pure 5 100都会返回5。

2. liftA2 q f g x = q (f x) (g x)

liftA2的通用类型是Applicative f => (b -> c -> d) -> f b -> f c -> f d。对于((->) a),它被特化为:

liftA2 :: (b -> c -> d) -> (a -> b) -> (a -> c) -> (a -> d)

翻译成人话就是:给一个二元函数q,再给两个从a出发的函数f(返回b)和g(返回c),liftA2会帮你组合出一个新函数——这个新函数接受一个a类型的参数x,先分别用x调用f和g得到b和c,再用q把这两个值组合成d。

比如用加法作为q,f = \x -> x*2,g = \x -> x+3,那么liftA2 (+) f g就是一个函数,输入5的话,会计算(5*2) + (5+3) = 10 +8=18,完全符合定义的逻辑。

3. <*> f g x = f x (g x)

这是你最疑惑的部分,我们先从类型入手。(<*>)的通用类型是Applicative f => f (b -> c) -> f b -> f c,对于((->) a),它被特化为:

(<*>) :: (a -> b -> c) -> (a -> b) -> (a -> c)

注意这里的a -> b -> c其实是a -> (b -> c)(Haskell默认右结合),也就是第一个参数f是一个接受a后返回二元函数的函数,第二个参数g是接受a返回b的函数,<*>要把它们组合成一个接受a返回c的函数。

那定义里的(<*>) f g x = f x (g x)是什么意思?这其实是Haskell柯里化函数的语法糖!它等价于:

(<*>) f g = \x -> f x (g x)

也就是说,<*>本身只接受两个参数f和g,然后返回一个新的一元函数——这个新函数接受x,先调用f x得到一个b -> c的函数,再调用g x得到b值,最后把前者作用在后者上得到c。

举个实际例子:假设f = \x y -> x * y(也就是乘法函数(*),类型Num a => a -> a -> a),g = \x -> x + 2,那么f <*> g就是一个函数,输入5的话,会计算f 5 (g 5) = 5 * (5+2) = 35。如果再链式调用,比如(+) <*> f <*> g,那输入5就是(+)(f 5)(g 5) = (5*5) + (5+2) =25+7=32,完美符合Applicative的组合逻辑。

为什么<*>看起来有三个参数?

这完全是Haskell的柯里化特性导致的。Haskell里没有真正的多参数函数,所有“多参数”函数都是通过返回函数来实现的:

  • <*>的本质是一个二元函数,接受f和g两个参数,返回一个一元函数。
  • 定义里写(<*>) f g x = ...只是一种更直观的写法,等价于把返回的一元函数的参数x直接写在定义里,让逻辑看起来更清晰——不用额外写lambda表达式。

简单说,你看到的三个参数,其实是<*>本身的两个参数,加上它返回的函数的一个参数,并不是<*>真的需要三个参数。


内容的提问来源于stack exchange,提问作者Michiel Borkent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:06:05