简体   繁体   English

Applicative 接口是否提供了超越将多参数函数(以柯里化形式)提升到 Functor 的能力?

[英]Does the Applicative interface provide power beyond the ability to lift multi-argument functions (in curried form) into a Functor?

Applicatives are often presented as a way to lift multi-argument functions into a functor and apply functor values to it.应用程序通常作为一种将多参数函数提升为函子并将函子值应用于它的方式呈现。 But I wonder if there is some subtle additional power stemming from the fact that it can do so by lifting functions that return a function and applying the function arguments one at a time.但我想知道是否有一些微妙的额外功能源于它可以通过提升返回 function 的函数并一次应用 function arguments 来实现这一点。

Imagine instead we define an interface based on lifting functions whose argument is a tuple of arguments:想象一下,我们定义一个基于提升函数的接口,其参数是 arguments 的元组:

# from Functor
fmap :: (a -> b) -> Fa -> Fb
# from Applicative
pure :: a -> Fa

# combine multiple functor values into a functor of a tuple
tuple1 :: Fa -> F(a)
tuple2 :: Fa -> Fb -> F(a,b)
tuple3 :: Fa -> Fb -> Fc -> F(a,b,c)
(etc ...)

# lift multi-argument functions (that take a tuple as input)
ap_tuple1 :: ((a) -> b) -> F(a) -> Fb
ap_tuple2 :: ((a,b) -> c) -> F(a,b) -> Fc
ap_tuple3 :: ((a,b,c) -> d) -> F(a,b,c) -> Fd
(etc ..)

Assume we had the corresponding tuple function defined for every sized tuple we may encounter.假设我们为我们可能遇到的每个大小的元组定义了相应的元组 function。 Would this interface be equally as powerful as the Applicative interface, given it allows for lifting/applying-to multi-argument functions BUT doesn't allow for lifting/applying-to functions that return a function?考虑到它允许提升/应用于多参数函数但不允许提升/应用于返回 function 的函数,该接口是否与 Applicative 接口一样强大? Obviously one can curry functions that take a tuple as an argument so they can be lifted in an applicative and one can uncurry functions that return a function in order to lift them into hypothetical implementation above.显然,可以对以元组作为参数的函数进行 curry,以便可以在应用程序中提升它们,并且可以对返回 function 的函数进行 uncurry,以便将它们提升到上面的假设实现中。 But to my mind there is a subtle difference in power.但在我看来,权力有细微的差别。 Is there any difference?有什么区别吗? (Assuming the question even makes sense) (假设这个问题甚至是有道理的)

You've rediscovered the monoidal presentation of Applicative .您重新发现了Applicative幺半群表示 It looks like this:它看起来像这样:

class Functor f => Monoidal f where
    (>*<) :: f a -> f b -> f (a, b)
    unit :: f ()

It's isomorphic to Applicative via:它通过以下方式与Applicative同构:

(>*<) = liftA2 (,)
unit = pure ()

pure x = x <$ unit
f <*> x = fmap (uncurry ($)) (f >*< x)

By the way, your ap_tuple functions are all just fmap .顺便说一句,您的ap_tuple函数都只是fmap The "hard" part with multiple values is combining them together.具有多个值的“硬”部分是将它们组合在一起。 Splitting them back into pieces is "easy".将它们拆分回碎片“很容易”。

Yes, this is equally as powerful.是的,这同样强大。 Notice that pure and tuple1 are the same.注意puretuple1是一样的。 Further, everything higher than tuple2 is recovered from tuple2 and fmap :此外,高于tuple2的所有内容都从tuple2fmap中恢复:

tuple3 x y z = repair <$> tuple2 (tuple2 x y) z
    where repair ((a, b), c) = (a, b, c)
tuple4 w x y z = repair <$> tuple2 (tuple2 x y) (tuple2 x y)
    where repair ((a, b), (c, d)) = (a, b, c, d)
-- etc.

Also, all of the ap_tuple s are just fmap :此外,所有ap_tuple都只是fmap

ap_tuple1 = fmap
ap_tuple2 = fmap
ap_tuple3 = fmap
-- ...

Renaming prod = tuple2 , your question boils down to重命名prod = tuple2 ,你的问题归结为

Is

class Functor f => Applicative f where pure:: a -> fa prod:: fa -> fb -> f (a, b)

equivalent to相当于

class Functor f => Applicative f where pure:: a -> fa liftA2:: (a -> b -> c) -> fa -> fb -> f c

? ?

And you might already see that the answer is yes.您可能已经看到答案是肯定的。 prod is just a specialization of liftA2 prod只是liftA2的专业化

prod = liftA2 (,)

But (,) is "natural" in the sense that it doesn't "delete" anything, so you can recover liftA2 just by destructuring the data back out:但是(,)是“自然的”,因为它不会“删除”任何内容,因此您可以通过解构数据来恢复liftA2

liftA2 f x y = f' <$> prod x y
    where f' (a, b) = f a b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM