應用式函子
在函數式程式設計中, 應用式函子,或簡稱應用式(applicative),是在函子和單子之間的中間結構。應用式函子允許函子式計算成為序列(不同於平常函子),但是不允許使用前面計算的結果於後續計算的定義之中(不同於單子)。應用式函子是範疇論中具有張量強度的不嚴格么半群函子的編程等價者。
應用式函子是2008年Conor McBride和Ross Paterson在他們的論文《Applicative programming with effects》中介入的[1]。應用式函子在Haskell中最初作為庫特徵出現,現在已經傳播到了其他語言,包括Idris、Agda、OCaml、Scala和F#。為了方便使用應用式函子編程,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
的值上進行運算,其錯誤由應用式機制自動處理。例如,要加1
到n :: Maybe Int
,只需要寫:
(+1) <$> n
如果n = Nothing
,則結果將是Nothing
;而如果n = Just k
,則結果會是Just (k+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.0 2.1 Hutton, Bride. Programming in Haskell 2. 2016: 157–163.
- ^ 3.0 3.1 3.2 Control.Applicative. [2021-02-08]. (原始內容存檔於2021-03-16).