我在 Hoogle 上找不到任何信息,但是否有一个带有类似签名的标准函数或运算符:
func :: (a -> b -> c) -> (a -> b) -> a -> c
即给定两个函数 f
和 g
,以及一个元素 x
作为参数,它计算出 f x (g x)
?
func :: (a -> b -> c) -> (a -> b) -> a -> c
即给定两个函数 f
和 g
,以及一个元素 x
作为参数,它计算出 f x (g x)
?
你寻找的函数是(<*>)
。为什么呢?因为确实(<*>)
具有更一般化的类型:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
但是要考虑到我们可以将 f
特化为 (->) r
,这个类型有一个 Applicative
实例:
(<*>) :: (->) r (a -> b) -> (->) r a -> (->) r b
...然后我们可以重新排列类型,使得->
成为中缀而不是前缀,这通常是这样的:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
这与您的签名模α重命名相同。
这样做是因为函数类型(->)
拥有Functor
、Applicative
和Monad
的实例,它们在习惯上被称为“reader”。这些实例将额外的参数线程传递到它们所有的参数中,这正是您的函数所做的。
f <*> g
表示函数 f 和函数 g 组合,等同于 (f . g)
。
是的,这是ap :: Monad m => m (a -> b) -> m a -> m b
的一个特殊情况。
这里你应该将monad m
看作带有参数的函数(->) r
。现在[source]中定义了ap
:
ap m1 m2 = do
x1 <- m1
x2 <- m2
return (x1 x2)
Which is thus syntactical sugar for:
ap m1 m2 = m1 >>= (\x1 -> m2 >>= return . x1)
>>=
在(->) r实例中定义为[source]:instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
return = const
(return
默认等于pure
,并且被定义为const
)。
这意味着:
ap f g = f >>= (\x1 -> g >>= const . x1)
= f >>= (\x1 -> (\r -> (const . x1) (g r) r))
= \x -> (\x1 -> (\r -> (const . x1) (g r) r)) (f x) x
现在我们可以进行beta约简(x1
是(f x)
):
ap f g = \x -> (\r -> (const . (f x)) (g r) r) x
另一个 beta 缩减(r
是 x
):
ap f g = \x -> (const . (f x)) (g x) x
const
展开为\c -> c
,将(.)
展开为f . g
,得到`\z -> f (g z)`。请注意保留HTML标签。ap f g = \x -> ((\c _ -> c) . (f x)) (g x) x
= \x -> (\z -> (\c _ -> c) ((f x) z)) (g x) x
z
是(g x)
,c
是((f x) (g x))
):ap f g = \x -> ((\c _ -> c) ((f x) (g x))) x
= \x -> (\_ -> ((f x) (g x))) x
_
为 x
):ap f g = \x -> ((f x) (g x))
现在我们将x
移到函数头部:
ap f g x = (f x) (g x)
f x y
缩写为(f x) y
,这意味着:ap f g x = (f x) (g x)
= f x (g x)
这是被请求的函数。
<*>
泛化了。 - chi