函数式编程中, 应用式函子,或简称应用式(applicative),是在函子单子之间的中间结构。应用式函子允许函子式计算成为序列(不同于平常函子),但是不允许使用前面计算的结果于后续计算的定义之中(不同于单子)。应用式函子是范畴论中具有张量强度英语Strong monad不严格幺半群函子英语Monoidal functor的编程等价者。

应用式函子是2008年Conor McBride和Ross Paterson在他们的论文《Applicative programming with effects》中介入的[1]。应用式函子在Haskell中最初作为库特征出现,现在已经传播到了其他语言,包括IdrisAgdaOCamlScalaF#。为了方便使用应用式函子编程,Glasgow Haskell和Idris二者现在提供了专门设计的语言特征。在Haskell中,应用式函子实现在Applicative类型类中。

定义 编辑

在Haskell中,应用式是参数化类型,被当作这个类型的数据的容器,加上两个方法:pure<*>。考虑一个参数化类型f a,类型f的一个应用式的pure方法有着类型:

pure :: a -> f a

它可被认为是把值带入应用式。类型f的应用式<*>方法有着类型:

(<*>) :: f (a -> b) -> f a -> f b

它可被认为是在应用式内部函数应用的等价者[2]

可作为替代,不提供<*>,转而提供一个叫做liftA2的函数。这两个函数都可以依据另一个来定义,因此在极小化完备定义中只需要其中一个[3]

应用式还要求满足四个方程式定律[3]

  • 同一:pure id <*> v = v
  • 复合:pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
  • 同态:pure f <*> pure x = pure (f x)
  • 互换:u <*> pure y = pure ($ y) <*> u

所有应用式都是函子。出于明确性,给定方法pure<*>fmap可以被实现为[3]

fmap f x = pure f <*> x

常用的表示法f <$> x等价于pure f <*> x

例子 编辑

在Haskell中,Maybe类型可以做成类型类Applicative的实例,使用下列定义[2]

instance Applicative Maybe where
    -- pure :: a -> Maybe a
    pure a = Just a

    -- (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
    Nothing  <*> _        = Nothing
    _        <*> Nothing  = Nothing
    (Just g) <*> (Just x) = Just (g x)

如定义章节所述,pure将一个a转变成一个Maybe a,而<*>应用一个Maybe函数到一个Maybe值。对类型a使用Maybe应用式,允许在类型a的值上进行运算,其错误由应用式机制自动处理。例如,要加1n :: Maybe Int,只需要写:

(+1) <$> n

如果n = Nothing,则结果将是Nothing;而如果n = Just k,则结果会是Just (k+1)。这个例子还展示了应用式如何允许某种泛型函数应用。

参见 编辑

引用 编辑

  1. ^ McBride, Conor; Paterson, Ross. Applicative programming with effects. Journal of Functional Programming. 2008-01-01, 18 (1): 1–13. ISSN 1469-7653. doi:10.1017/S0956796807006326. 
  2. ^ 2.0 2.1 Hutton, Bride. Programming in Haskell 2. 2016: 157–163. 
  3. ^ 3.0 3.1 3.2 Control.Applicative. [2021-02-08]. (原始内容存档于2021-03-16). 

外部链接 编辑