【函數(shù)式】Monads模式初探——Functor

函子與范疇

函子(functor)是從一個范疇到另一個范疇的轉(zhuǎn)換,并且其亦可轉(zhuǎn)換/保持態(tài)射(morphism)。
一個態(tài)射是從一個范疇里的一個值到同一個范疇里的另一個值的變換。在貓的范疇的例子里,一個態(tài)射好比一個盒子,能夠把黯淡無光的貓轉(zhuǎn)化為一個霓虹閃耀的貓勋磕。在類型的范疇里(計算機科學(xué)常用的范疇),一個態(tài)射是一個把某類型轉(zhuǎn)化為另一個類型的函數(shù)敢靡。
函子是可以把貓轉(zhuǎn)化為狗的東西(不同范疇的轉(zhuǎn)換)挂滓。函子可以把暗淡的貓轉(zhuǎn)換成暗淡的狗,光彩的貓轉(zhuǎn)換成光彩的狗啸胧。函子還可以連態(tài)射都轉(zhuǎn)換過去赶站,這樣可以把暗淡的狗轉(zhuǎn)化為光彩的狗。


圖中纺念,下面的圈子表示所有的類型組成的范疇贝椿。里面包括標(biāo)準的String、Double和其他Scala能定義的類型陷谱。函子F是Scala里的一個類型構(gòu)造器烙博。對于一個范疇中的任意類型T,可以把該類型置于類型構(gòu)造器F[_]中烟逊,從而得到一個新類型F[T]渣窜。

對函子的描述

函子本質(zhì)上是范疇之間的轉(zhuǎn)換。



上圖表示范疇C到范疇D的函子宪躯。圖中乔宿,對象A和B被轉(zhuǎn)換到了范疇D中同一個對象,因此访雪,態(tài)射g就被轉(zhuǎn)換成了一個源對象和目標(biāo)對象相同的態(tài)射(不一定是單位態(tài)射)详瑞,而且id_A和id_B變成了相同的態(tài)射掂林。對象之間的轉(zhuǎn)換是用淺黃色的虛線箭頭表示,態(tài)射之間的轉(zhuǎn)換是用藍紫色的箭頭表示坝橡。

范疇之間的轉(zhuǎn)換必須在轉(zhuǎn)換時保留所有的態(tài)射才能稱為函子轉(zhuǎn)換泻帮。也就是說,如果在第一個范疇有個操作類型的函數(shù)驳庭,那么我們也應(yīng)該有個轉(zhuǎn)換后的函數(shù)能夠操作轉(zhuǎn)換后的類型刑顺。比如說,如果我們有個吧String轉(zhuǎn)換為Int的函數(shù)饲常,那么我們也應(yīng)該能夠把F[String]轉(zhuǎn)換成F[Int],這正是map方法所提供的功能狼讨。

trait Functor[F[_]] {
  def apply[A](x: A): F[A]
  def map[A, B](x: F[A])(f: A => B): F[B]
}

apply方法的作用——對于任意類型A贝淤,一個函子能夠在新范疇里構(gòu)造一個類型F[A]。
map方法的作用——給定一個轉(zhuǎn)換后的類型F[A]和一個在原范疇里的態(tài)射A => B政供,能夠創(chuàng)建一個F[B]類型的結(jié)果播聪。也就是說,我們有個新函數(shù)能夠接受F[A]布隔,返回F[B]离陶。

簡單的說,函子是實現(xiàn)了map方法的數(shù)據(jù)類型衅檀。
舉例來說招刨,

trait Functor[F[_]] {
  def fmap[A, B](x: F[A])(f: A => B): F[B]
}

object ListFunctor extends Functor[List] {
  def fmap[A, B](list: List[A])(f: A => B): List[B] = list map f
}

val l1 = List(1, 2, 3)
val result = ListFunctor.fmap(l1)(i => i+1)
println(result)
// print is
// List(2, 3, 4)

函子的形象演示

假設(shè)有一個容器(container),這里的容器可以認為是一種上下文(context)或者是為函數(shù)提供的計算上下文(computational context)哀军。
在圖中表示為一個盒子沉眶。當(dāng)一個元素被上下文包裹,我們不能簡單的對該元素應(yīng)用一般的運算方法杉适,于是需要使用map函數(shù)(Haskell中稱為fmap)谎倔。



map函數(shù)知道如何將普通函數(shù)應(yīng)用到一個被上下文包裹的元素上。


函子(functor)是定義了如何應(yīng)用map的類型類(typeclass)猿推。



如果我們要將普通函數(shù)應(yīng)用到一個有盒子上下文包裹的值片习,那么我們首先需要定義一個叫Functor的數(shù)據(jù)類型,在這個數(shù)據(jù)類型中需要定義如何使用map或fmap來應(yīng)用這個普通函數(shù)蹬叭。


函子內(nèi)部工作原理可以認為是這樣的:

  1. 將值從上下文盒子中解救出來
  1. 將外部指定的函數(shù)(+3)應(yīng)用到這個值上藕咏,得到一個新的值(5)
  2. 再將這個新值放入到上下文盒子中

下圖顯示了如何將一個普通函數(shù)應(yīng)用到值集合,不是單個值具垫,而是值的集合數(shù)組中侈离,圖中數(shù)組函子將數(shù)組一個個打開(遍歷),然后分別將普通函數(shù)應(yīng)用到這些元素中筝蚕,最后返回一個新的集合值卦碾。


補充:高階類型

基本泛型:



如果類型參數(shù)也是一個泛型(類型構(gòu)造器):



對類型的歸納:

類型(type)是對數(shù)據(jù)的抽象铺坞,而高階類型(higher-kinded type)是對類型的抽象:


參考資料

函數(shù)編程中functor和monad的形象解釋
深入理解Scala
理解高階類型
Scala和范疇論 -- 對Monad的一點認識

轉(zhuǎn)載請注明作者Jason Ding及其出處
jasonding.top
Github博客主頁(http://blog.jasonding.top/)
CSDN博客(http://blog.csdn.net/jasonding1354)
簡書主頁(http://www.reibang.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354進入我的博客主頁

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市洲胖,隨后出現(xiàn)的幾起案子济榨,更是在濱河造成了極大的恐慌,老刑警劉巖绿映,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擒滑,死亡現(xiàn)場離奇詭異,居然都是意外死亡叉弦,警方通過查閱死者的電腦和手機丐一,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淹冰,“玉大人库车,你說我怎么就攤上這事∮K” “怎么了柠衍?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長晶乔。 經(jīng)常有香客問我珍坊,道長,這世上最難降的妖魔是什么正罢? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任阵漏,我火速辦了婚禮,結(jié)果婚禮上腺怯,老公的妹妹穿的比我還像新娘袱饭。我一直安慰自己,他們只是感情好呛占,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布虑乖。 她就那樣靜靜地躺著,像睡著了一般晾虑。 火紅的嫁衣襯著肌膚如雪疹味。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天帜篇,我揣著相機與錄音糙捺,去河邊找鬼。 笑死笙隙,一個胖子當(dāng)著我的面吹牛洪灯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竟痰,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼签钩,長吁一口氣:“原來是場噩夢啊……” “哼掏呼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起铅檩,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤憎夷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后昧旨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拾给,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年兔沃,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒋得。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡粘拾,死狀恐怖窄锅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情缰雇,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布追驴,位于F島的核電站械哟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏殿雪。R本人自食惡果不足惜暇咆,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丙曙。 院中可真熱鬧爸业,春花似錦、人聲如沸亏镰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽索抓。三九已至钧忽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逼肯,已是汗流浹背耸黑。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留篮幢,地道東北人大刊。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像三椿,于是被迫代替她去往敵國和親缺菌。 傳聞我的和親對象是個殘疾皇子葫辐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容