[英]what does (<*>) :: f (a -> b) -> f a -> f b exactly do in the Functor class
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
From my understanding, it takes a function f, where another function (a -> b)
as its argument, returns a function f
. 据我了解,它采用一个函数f,其中另一个函数
(a -> b)
作为其参数返回一个函数f
。 Applying f
to a
then returns a function f
and apply f
to b
. 将
f
应用于a
然后返回函数f
并将f
应用于b
。
Here is an example: 这是一个例子:
Prelude> (+) <$> Just 2 <*> Just 3
Just 5
But I don't quite understand how it works. 但是我不太了解它是如何工作的。
I guess (+)
should be f
, Just 2
and Just 3
should be a
and b
respectively. 我猜
(+)
应该是f
, Just 2
和Just 3
应该分别是a
和b
。 Then what is (a -> b)
? 那么
(a -> b)
什么?
From my understanding, it takes a function f...
据我了解,它需要一个函数来...
Unfortunately this is incorrect. 不幸的是,这是不正确的。 In this case,
f
is a type, not a function. 在这种情况下,
f
是类型,而不是函数。 Specifically, f
is a "higher-kinded type" with kind * -> *
. 具体地说,
f
是类型为* -> *
的“高级类型”。 The type f
is the functor. 类型
f
是函子。
In this case, f
is Maybe
. 在这种情况下,
f
是Maybe
。 So we can rewrite the function types, specializing them for Maybe
: 因此,我们可以重写函数类型,使其专门用于
Maybe
:
pure :: a -> Maybe a
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
It starts to become a bit clearer once you get this far. 到此为止,它将变得更加清晰。 There are a couple different possible definitions for
pure
, but only one that makes sense: 对于
pure
,有两种不同的可能定义,但是只有一种才有意义:
pure = Just
The operator x <$> y
is the same as pure x <*> y
, so if you write out: 运算符
x <$> y
与pure x <*> y
,因此如果您写出:
(+) <$> Just 2 <*> Just 3
Then we can rewrite it as: 然后我们可以将其重写为:
pure (+) <*> pure 2 <*> pure 3
Although this technically has a more general type. 尽管从技术上讲,这是更通用的类型。 Working with the functor laws, we know that
pure x <*> pure y
is the same as pure (xy)
, so we get 使用函子定律,我们知道
pure x <*> pure y
与pure (xy)
相同,因此我们得到
pure ((+) 2) <*> pure 3
pure ((+) 2 3)
pure (2 + 3)
In this case, we a
and b
are the types but since <*>
appears twice they actually have different types in each case. 在这种情况下,我们
a
和b
是类型,但是由于<*>
出现两次,因此它们实际上在每种情况下都有不同的类型。
In the first <*>
, a
is Int
and b
is Int -> Int
. 在第一个
<*>
, a
为Int
, b
为Int -> Int
。 In the second <*>
, both a
and b
are Int
. 在第二个
<*>
, a
和b
均为Int
。 (Technically you get generic versions of Int
but that's not really important to the question.) (从技术上讲,您获得的是
Int
通用版本,但这对问题并不是很重要。)
Applicative functors were introduced to Haskell as applicative style programming "Idioms" . 应用函子作为应用样式编程“成语”引入Haskell。 Unpacking this phrase, we have "applicative style programming";
解开这个短语,我们有“应用样式编程”; which is just application of functions to arguments.
这只是函数对参数的应用。 We also have "idioms", or phrases in a language which have a special meaning.
我们也有“成语”或具有特殊含义的语言短语。 For example "raining cats and dogs" is an idiom for raining very heavily.
例如,“给猫和狗下雨”是下大雨的习语。 Putting them together, applicative functors are function applications with special meaning.
应用函子放在一起,是具有特殊含义的函数应用程序。
Take for example, following Dietrich Epp's lead, anApplication
defined by a function, 例如,在Dietrich Epp的带领下,一个函数定义了一个
anApplication
,
anApplication = f a
where
f = (+2)
a = 3
and, anIdiomaticApplication
, defined with idiomatic application, 和
anIdiomaticApplication
,通过惯用应用程序定义,
anIdiomaticApplication = f <*> a
where
f = Just (+2)
a = Just 3
The top level structure of these definitions are similar. 这些定义的顶层结构相似。 The difference?
区别? The first has a space--normal function application--and the second has
<*>
--idiomatic function application. 第一个具有空格-正常功能应用程序-第二个具有
<*>
惯用功能应用程序。 This illustrates how <*>
facilitates applicative style: just use <*>
in place of a space. 这说明
<*>
如何促进应用风格:只需使用<*>
代替空格。
The application, <*>
, is idiomatic because it carries a meaning other than just pure function application. 应用程序
<*>
是惯用的,因为它具有除纯函数应用程序以外的含义。 By way of exposition, in anIdiomaticApplication
we have something like this: 通过说明的方式,在一个
anIdiomaticApplication
我们有这样的东西:
f <*> a :: Maybe (Int -> Int) <*> Maybe Int
Here, the <*>
in the type is used to represent a type level function* that corresponds to the signature of the real <*>
. 在此,类型中的
<*>
用于表示与真实<*>
签名相对应的类型级别函数*。 To the type- <*>
we apply the type arguments for f
and a
(respectively Maybe (Int -> Int)
and Maybe Int
). 对于类型
<*>
我们将f
和a
(分别为Maybe (Int -> Int)
和Maybe Int
)应用类型参数。 After application we have 申请后,我们有
f <*> a :: Maybe Int
As an intermediate step, we can imagine something like 作为中间步骤,我们可以想像
f <*> a :: Maybe ((Int -> Int) _ Int)
With _
being the type level stand-in for regular function application. _
是常规功能应用程序的类型级别替身。
At this point we can finally see the idiom-ness called out. 在这一点上,我们终于可以看到习惯用语了。
f <*> a
is like a normal function application, (Int -> Int) _ Int
, in the Maybe
context/idiom. 在
Maybe
上下文/习惯用法中, f <*> a
类似于常规函数应用程序(Int -> Int) _ Int
。 So, <*>
is just function application that happens within a certain context. 因此,
<*>
只是在特定上下文中发生的函数应用程序。
In parting, I'll emphasize that understanding <*>
is only partially understanding its use. 在分开时,我将强调理解
<*>
仅部分理解其用法。 We can understand that f <*> a
is just function application which some extra idiomatic meaning. 我们可以理解,
f <*> a
只是函数应用程序,具有一些特殊的含义。 Due to the Applicative laws, we can also assume that idiomatic application will be somehow sensible. 根据适用法律,我们还可以假定惯用的应用会在某种程度上是明智的。
Don't be surprised, however, if you look at <*>
and get confused since there is so little there. 但是,如果您查看
<*>
并感到困惑,因为那里的内容很少,请不要感到惊讶。 We must also be versed in the various Haskell Idioms. 我们还必须精通各种Haskell习语。 For instance, in the
Maybe
idiom either the function or value may not be present, in which case the output will be Nothing
. 例如,在
Maybe
惯用语中,函数或值都可能不存在,在这种情况下,输出将为Nothing
。 There are of course, many others, but getting familiar with just Either a
and State s
should model a wide variety of the different kinds. 当然,还有很多其他人,但是只要熟悉
Either a
和State s
,就应该为各种不同的模型建模。
*Something like this could actually be made with a closed type family (untested) *像这样的事情实际上可以由封闭型家庭(未经测试)完成
type family IdmApp f a where
IdmApp (f (a->b)) a = f b
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.