單子,想弄不懂都很難

2021-09-14 04:47:40 字數 3411 閱讀 8818

c 語言裡沒有現代程式設計師熱衷於討論的那些東西。

不過,那些東西不是原本就沒有麼?

下面我嘗試用 c 語言來寫乙個單子(monad)。

看下面這段**:

typedef struct  maybe;
在 c 語言裡,這是個結構體,而且是乙個似乎很無聊的結構體。這種結構體能用來做什麼呢?

可以作為函式的返回值型別。例如:

maybe foo(void *thing)

;}

假設foo像下面這樣呼叫:

maybe a = foo(thing); /* thing 指向前面出現的某個變數 */
那麼,當a.thingnull時,表示foo函式執行失敗,否則表示執行成功。

那麼foo函式的作用就將一種型別包裝成maybe型別。

null可能會嚇著一些對 c 語言原本就沒怎麼有好感的人,可以給它換個名字:

#define nothing null
現在,可以認為當a.thingnothing時,表示foo函式執行失敗,否則表示執行成功。

接下來,為maybe型別定義這樣的函式:

maybe aha(void * (*f)(void *), maybe a)

這個函式可以將乙個函式f作用於a.thing。假設這個f為:

void *textize(void *thing)

有了像textize這樣的函式,就可以用aha函式了,如下:

int a = 2;

maybe x = aha(textize, foo(&a));

結果得到的x.thing會指向乙個字串"2"

乙個型別再加上乙個針對這種型別的aha這樣的函式,叫函子

現在,再為maybe型別構造乙個函式:

maybe bar(maybe a, maybe (*contuation)(void *thing))

;}

現在,可以宣布有了乙個maybe單子。

這個bar函式有什麼用呢,它能夠按照順序安全地組合一組形狀相同的函式,從而起到乙個函式的效果。例如,對於下面的三個函式:

maybe test_a(void *thing)

maybe test_b(void *thing)

maybe test_c(void *thing)

使用bar可以把它們按照順序裝配起來:

int a = 2;

maybe x = bar(bar(bar(foo(&a), test_a), test_b), test_c);

結果x.thing依然是指向變數a的指標,經過一組函式的處理,a的值變成了 3000。

與上述**等價的**,也是 c 程式設計師慣用的**如下:

int a = 2;

maybe x = foo(&a);

if (x.thing)

}}

乙個單子,由一種型別以及針對這種型別的類似foobar這樣的函式構成。

上面我用的fooaha以及bar這些名字,有一些惡意的調侃。值得注意的是,aha函式實際上可以基於foobar來定義。例如:

maybe aha(void * (*f)(void *), maybe a)

雖然稍微有點繞圈子,但是aha的確是基於foobar定義了出來。這說明了什麼呢?

單子的層次高於函子。

倘若你能理解上述**所體現出來的形式,那麼上面出現的東西是叫物件、態射、函子、自函子、自然變換、自函子範疇、么半群、單子,還是別的什麼東西,很重要嗎?我以為這些東西只是對研究數學的人很重要,而對於程式設計的人來說……只要你寫的**足夠簡約,足夠具備復用性,那麼就一點都不重要。

倘若覺得很重要,那麼好吧,就掰扯一下,以問答的形式。

q:什麼是範疇?

a:範疇由物件和態射構成。例如,c 語言裡的資料型別與函式。

q:什麼是函子?

a:函子可以將一種物件變成另一種物件,將一種態射變成另一種態射。例如,上面的maybe,將void *變成了maybe型別;上面的ahatextize這種void * -> void *的函式變成了maybe -> maybe的函式。

q:什麼是自函子?

a:將乙個範疇裡的物件和態射變成這個範疇裡的物件和態射的函子就是自函子。作家、畫家、歌唱家、演員、舞者、政客、運動員……從事各種職業的人,都是自函子。什麼職業都不從事的人也是自函子,他們就是foo函式。也有一些不是自函子的人,多數在精神病院裡,還有一些在外面跳大神。

q:什麼是自函子範疇?

a:乙個自函子構成的範疇。這個範疇裡就乙個東西,這個自函子。這個範疇裡面的態射,叫自然變換。foobar都是自然變換。

q:什麼是自函子範疇上的么半群?

a:將自函子範疇裡的所有態射視為集合,那個自函子就消失了。也就是說,自函子轉化成了乙個態射集合,這個集合叫 hom-集。想一想自個,當你愛上乙個人或什麼東西的時候,你就消失了,我們管這個叫忘我。過去的人思慕成仙,要成仙,首先要忘我,然後去搞行為藝術。藝術是永恆的,對吧?這種行為藝術怎麼搞呢?需要先搞乙個么元(也有很多人叫單位元)。這個么元啊,就是眼觀鼻、鼻觀心、意守丹田。有了么元,就可以驅動真氣,打通任督二脈……做到這兩步,就得到了么半群。

q:玄學?

a:計算機裡執行的玄學。

弄不懂什麼是雲原生?看完這篇文章就夠了!

雲原生 很多人會對這個新名詞感到困惑,到底什麼是雲原生,雲原生又能給我們帶來什麼呢?其實雲原生的概念最早是由來自pivotal的mattstine於2013年首次提出,這是他根據自身多年的架構和諮詢經驗總結出來的乙個思想集合,得到了開源社群的不斷完善,並被一直延續使用至今。一 什麼是雲原生 那麼到底...

看看這個常常被初級程式設計師弄不懂的 「事件」

眾所周知在面試中,經常有些崽子面試官會問些 事件和委託 的關係,也許一路走來的程式設計師大多都會被問到這個,那麼對於這個 高頻的 事件和委託 問題,如何回擊呢?首先我從最經典的一套面試題說起,用事件來實現 貓爪老鼠 這是乙個從網上copy過來的一 個例子。static void main strin...

企業郵箱怎麼弄 想給公司弄個企業郵箱怎麼開通呢?

這幾年越來越意識到企業郵箱的重要性了,建個官網 印個名片 客戶的合同對接 員工的一些管理,沒有郵箱對企業形象是乙個很大的損失。企業郵箱更加正式也更方便管理。想申請個企業郵箱,要從何開始呢?管理員工郵箱更高效 管理員的強大管理功能,可有效提公升企業郵箱的安全性,也讓管理員工的郵箱變得更簡單。分級管理員...