Haskell中的x <*> y <$> z

hgi*_*sel 5 haskell functor applicative

我正在尝试理解一些Haskell源代码,我有时会遇到这种结构:

x <*> y <$> z
Run Code Online (Sandbox Code Playgroud)

例如

(+) <*> (+1) <$> a
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释这个结构吗?我得到它转换为fmap a (+ a + 1),但我无法建立连接

dup*_*ode 4

让我们从以下开始:

x <*> y <$> z
Run Code Online (Sandbox Code Playgroud)

加上括号,就变成:

(x <*> y) <$> z
Run Code Online (Sandbox Code Playgroud)

鉴于此 (<$>) :: Functor f => (a -> b) -> f a -> f b,我们有:

x <*> y :: a -> b
z :: Functor f => f a
Run Code Online (Sandbox Code Playgroud)

鉴于此(<*>) :: Applicative g => g (c -> d) -> g c -> g d,我们有:

x :: Applicative g => g (c -> d)
y :: Applicative g => g c
x <*> y :: Applicative g => g d
Run Code Online (Sandbox Code Playgroud)

结合最后几个结果,我们得到:

g d ~ a -> b
g ~ (->) a
d ~ b

x :: a -> c -> b
y :: a -> c
x <*> y :: a -> b
Run Code Online (Sandbox Code Playgroud)

所以:

(\x y z -> x <*> y <$> z) :: Functor f => (a -> c -> b) -> (a -> c) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

现在知道(<*>)正在使用函数实例,我们还可以替换它的定义:

x <*> y <$> z
(\r -> x r (y r)) <$> z
Run Code Online (Sandbox Code Playgroud)

在你的例子中,x = (+)y = (+1)z = a,所以我们得到......

(\r -> r + (r + 1)) <$> a
Run Code Online (Sandbox Code Playgroud)

...将每个值添加a到自身加一:

GHCi> (+) <*> (+1) <$> [0..3]
[1,3,5,7]
GHCi> ((+) <*> (+1) <$> (*5)) 2
21
Run Code Online (Sandbox Code Playgroud)

  • @Lazersmoke我确实认为“Applicative ((-&gt;) r)”有一些合法的用途(特别是“op &lt;$&gt; f &lt;*&gt; g”,如果“f”和`g` 是函数,要么非常明显,要么与上下文无关)。无论如何,我们正在讨论的例子不是其中之一。(我同意 chi 的观点,因为使用独立的 `(&lt;*&gt;)` 作为 S 组合器往往会令人困惑。) (2认同)