scala與函式式程式設計 從範疇論看函式式程式設計

2021-07-31 20:44:00 字數 2563 閱讀 1251

那麼,當我們的**與範疇又有什麼關係呢?在談論程式設計時,我們所在的又是什麼範疇呢?

public

class

company

public

class

employee

public

static employee getsupervisor(employee e1)

public

static company getwork(employee e)

public

static string getname(employee e)

我們不妨這樣定義上面那段**所描繪的範疇:這個範疇下至少有三個點:string, employee, company。而getsupervisor,getwork和getname則形成了這三個點之間的關聯關係。

點:資料型別

每種資料型別其實是乙個集合,比如integer這個型別就代表了整數的集合,而string則是字串物件的集合。然而集合也可以是範疇中的乙個點,就像螳螂是動物這個範疇中的乙個點一樣。語言中可能預先定義了很多點,而我們定義的employee和company則形成了兩個新的點。

箭頭:函式

函式function(oo中的方法,可以轉換為函式的形式,見第一篇)從數學的角度定義,就是兩個集合之間的對映關係:a->b的函式是指a中的每個元素都能對應到b中的某個元素。但是在程式語言的範疇中,我們可以忽略a, b中的具體元素,轉而直接將a和b作為範疇中的元素。

那麼,所有的函式就成為了具體的某一根箭頭,如getname就成為了employee->string的一根箭頭,而getsupervisor則是employee->employee的箭頭。

如果函式有多個入參怎麼辦?比如add(int a, int b) 。正如函式簽名所暗示的那樣,我們可以把(a,b)看作是乙個整體,將乙個二元組對映為乙個整數。因此,(a,b)二元組也是一種資料型別。

大多數靜態型別的語言都可以歸入上面的範疇,但函式式程式設計的核心——函式組合,還沒有體現出來。比如最常見的map(f: a->b, list: list[a]):list[b]。

此處需要引入函子functor的概念。

如果兩個範疇c和d,如果c範疇中的每個元素都能對應到d範疇中的某個元素(注意與函式一樣,不要求是一對一關聯,可以是多對一),並且c範疇中的箭頭也能對應到d範疇中的箭頭,那麼這種範疇與範疇之間的對映就是一種函子functor。

比如在上海領導班子這個範疇中,有市委書記、市長、各區區長等元素;在江蘇省領導班子這個範疇中,有省委書記、省長、各市市長等元素。那麼上海領導班子中的市委書記就能對映為江蘇省領導班子中的省委書記,而市長能對映為省長,說明了兩個範疇之間的元素是可以對映的(此處是一對一關係);並且市委書記與市長的關係,在省委書記與省長之間依然成立,說明了範疇之間的箭頭也是可以對映的。因此,這種對映的方式就是乙個functor。

同樣在這兩個範疇中,如果將上海領導班子中的市長對映為江蘇省領導班子中的市長,那麼原先的一些關係在新範疇中將不能找到對應關係,因此不是每種對映都能成為一種functor。

如果add(int a, int b) = a+b,那麼如果固定a不變,只變化b,結果會如何呢?比如在a=1的條件下,就變成了add(b) = 1+b。因此add(a,b)不僅可以看作是(a,b) -> int的對映,也能看作是a->(b->int)的一種對映。想像一下給定任何a=x,都會產生乙個相應的新函式,這個函式的功能是將乙個int+x。

再看map(f: a->b, list: list[a]):list[b]這個簽名,可以看作是(f, list[a])的二元組對映為list[b]。但如果換乙個角度,則可以看作是給定乙個f:a->b,得到乙個新的函式mapf:list[a]->list[b]。

我們已經知道,a和b作為兩種型別是原範疇中的兩個點,那麼list[a]和list[b]呢?我們把它們看作是新範疇list中的兩個型別list[a]和list[b]。而對映這兩個範疇的方式,則是將x對映為list[x],那麼以前在a,b之間存在的箭頭都要能在list[a]和list[b]之間找到對應的箭頭。這些箭頭是範疇中元素之間的對映,而在程式語言中,就是a->b的函式。

因此,假如給定任一f:a->b,經過map方法之後,如果都能產生乙個全新的函式list[a]->list[b],那麼原範疇中的每個箭頭都能在新範疇中找到對應的對映。這就符合了functor的定義。

所以,map(a->b, list[a]):list[b]的每一種實現,都是從原範疇對映到list範疇的乙個functor。在scala中,functor的簽名可以定義為這樣的trait:

trait

functor[f[_]]

從範疇論的角度看函式式程式設計,會產生一種全新的理解。oo之後人們以構建和封裝物件的角度來看待程式設計,一度使程式設計與數學脫離。但函式式程式設計的出現,則讓我們重新從數學理論的視角出發,將程式設計與數學又一次地聯絡在了一起。

這種視角讓我們更好地了解到oo語言與函式式語言之間設計哲學上的差異。儘管函式式程式設計的門檻更高,但由於其表現力、生產率和背後的數學基礎,這類語言仍然值得我們投入更多的時間和精力去探索和學習。

SCALA函式式程式設計

建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 scala的語法規定,將函式賦值給變數時,必須在函式後面加上空格和下劃線 正常宣告乙個帶有乙個字串型別引數,並返回unit型別的方法 sca...

Scala函式式程式設計

知識點1.scala的柯里化技術,允許將接受多個引數的函式,轉變為接受單一引數的函式 2.柯里化的作用可以允許使用者自建控制結構 object demo03 f1 a int,b int int def f11 a int b int f11 a int b int int def f2 a int...

Scala函式式程式設計

package com.yz6 import scala.collection.mutable.arraybuffer object test 定義乙個函式 軀殼 靈魂 def function0 name string unit println 你好 name 將乙個函式作為值傳遞給另乙個函式 在...