在 Haskell 中,如何将嵌套上下文中的函数“应用”到上下文中的值?

Cha*_*t1c 4 haskell function apply applicative

nestedApply :: (Applicative f, Applicative g) => g (f (a -> b)) -> f a -> g (f b)
Run Code Online (Sandbox Code Playgroud)

正如类型所示,如何将其(a->b)应用于a上下文中f

感谢帮助。

chi*_*chi 5

这是关注类型很有帮助的情况之一。我会尽量保持简单并解释原因。

让我们从描述任务开始。我们已经拥有gfab :: g(f(a->b))并且fa :: f a我们想要拥有g(f b)

gfab :: g (f (a -> b))
fa   :: f a
??1  :: g (f b)
Run Code Online (Sandbox Code Playgroud)

由于g是一个函子,为了获取类型,我们可以从类型g T值开始并将其应用于。在我们的例子中,我们有,所以我们正在寻找:??2g Ufmap??3 :: U -> TT = f b

gfab :: g (f (a -> b))
fa   :: f a
??2  :: g U
??3  :: U -> f b
??1 = fmap ??3 ??2  :: g (f b)
Run Code Online (Sandbox Code Playgroud)

现在看来我们应该选择??2 = gfab。毕竟,这是g Something我们拥有的唯一类型值。我们获得U = f (a -> b)

gfab :: g (f (a -> b))
fa   :: f a
??3  :: f (a -> b) -> f b
??1 = fmap ??3 gfab :: g (f b)
Run Code Online (Sandbox Code Playgroud)

让我们制作??3一个 lambda,\ (x :: f (a->b)) -> ??4其中??4 :: f b. ( 的类型x可以省略,但我决定添加它来解释发生了什么)

gfab :: g (f (a -> b))
fa   :: f a
??4  :: f b
??1 = fmap (\ (x :: f (a->b)) -> ??4) gfab :: g (f b)
Run Code Online (Sandbox Code Playgroud)

如何制作??4。好吧,我们有类型f (a->b)和的值f a,因此我们可以通过<*>这些值来获取f b。我们最终得到:

gfab :: g (f (a -> b))
fa   :: f a
??1 = fmap (\ (x :: f (a->b)) -> x <*> fa) gfab :: g (f b)
Run Code Online (Sandbox Code Playgroud)

我们可以将其简化为:

nestedApply gfab fa = fmap (<*> fa) gfab
Run Code Online (Sandbox Code Playgroud)

现在,这不是最优雅的方法,但理解这个过程很重要。