有没有一个标准函数可以计算 `f x (g x)`?

4
我在 Hoogle 上找不到任何信息,但是否有一个带有类似签名的标准函数或运算符:
func :: (a -> b -> c) -> (a -> b) -> a -> c

即给定两个函数 fg,以及一个元素 x 作为参数,它计算出 f x (g x)


3
你可能也想看一下 combinator S,它在 Haskell 中被 <*> 泛化了。 - chi
3个回答

10

你寻找的函数是(<*>)。为什么呢?因为确实(<*>)具有更一般化的类型:

(<*>) :: 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)

这与您的签名模α重命名相同。

这样做是因为函数类型(->)拥有FunctorApplicativeMonad的实例,它们在习惯上被称为“reader”。这些实例将额外的参数线程传递到它们所有的参数中,这正是您的函数所做的。


9

哦,是的!谢谢你。我本该自己知道这个的。 - mschmidt

2

是的,这是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 缩减(rx):

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

现在我们可以再次进行beta缩减(其中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

最后,我们进行了一次 beta-还原 (_x):
ap f g = \x -> ((f x) (g x))

现在我们将x移到函数头部:

ap f g x = (f x) (g x)

在Haskell中,f x y缩写为(f x) y,这意味着:
ap f g x = (f x) (g x)
         = f x (g x)

这是被请求的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接