Category_theory and Functor

漆楚衡發表於2014-08-01

我主要看了這個Category_theory,它介紹了Haskell中的範疇學應用,主要是Functor和Monad。
本文介紹範疇論和Functor。

範疇

組成部分:

  • 物件集合

  • 物件上的morphism(函式?)集合

  • 一個定義在morphism上的composition。

laws

  • 結合律:(f . g) . h = f . (g . h)
  • g . id = id . g,設g : A -> B,前一個id定義在A上,後一個物件定義在B上。(在介紹這個定律時,文中有提到範疇中的每一個物件都要有identity morphism。

在haskell中的範疇

  • 型別即物件

  • 函式即morphism

  • (.)即composition

Functor

Functor就是一種兩個範疇間的一一對映,設有源範疇C和目標範疇D:

  • 它將C中的每一個物件對映到D中,即F(A) (A ∈ C中的物件集)

  • 它將C中的每一個morphism f:A -> B對映到D中,即F(f) : F(A) -> F(B) (f ∈ C中的morphism集)

Functor laws

  • F(id) = id

  • 分佈律:F (f . g) = F f . F g

Haskell中的Functor

在haskell中的Functor typeclass即為Functor。可以看到,Functor的每一個例項都完成了這樣的對映:

  • 因為haskell中的Functor都是某種“包裝”,所以型別構造子可以視為物件到物件的“F”

  • fmap函式則完成了Functor中作用於morphism上的“F”, 即有原函式為f,則F(f)為fmap f


設有源範疇C和目標範疇D

haskell中的Functor提供了兩個平行世界之間的對映關係,我們可以將F(A)視為一個黑箱,我們知道它容納了一個型別A,我們可以向黑箱中輸入(通過fmap)一個f:A -> B 得到黑箱F(B),這樣便遮蔽了我們對箱子的操作,也就不需要對箱子有太多瞭解。

這種包裝的意義還在於包裝型別可以提供某種特性附加在操作之上。fmap f賦予了f運作黑箱的能力。這種能力依黑箱的不同而不同:

  • 對於Maybe Functor,fmap使得f可以接受失敗的輸入
  • 對於[] Functor, fmap使得f可以處理輸入集合
  • 對於IO Functor,IO是真實的黑箱。

獲得能力的只是fmap f,f本身並無任何改變,f所關心的始終是被包裝的值上的操作。於是可以看到Functor提供了一層抽象——把“環境”和被“環境”所包裹的“內容”分開,即,使我們可以定義專注面向“內容”的函式f,而使用Functor輕易就可以把f應用到某種“環境”中去。

在這裡可以聯想高階函式:把高階函式本身看成一種“模式”,而輸入的函式看成“模式”運作所需要的可嵌入元件。於是我們通過抽出“模式”實現了極為高效的程式碼複用。

不理解的地方

原文中有一個註腳提到了seq會破壞範疇的第二條law,可能是我英語水平有限,沒有理解他到底什麼意思,只看懂了結論是seq會破壞Haskell中的一些比較好的數學性質。

看來有必要找找關於求值和seq方面比較全面的資料看看。

附:原文中範疇論概念到Haskell的轉換總結

定義Haskell中的範疇為Hask

  • 我們僅運用Hask和它的子範疇
  • 物件是型別
  • Morphism是函式
  • 得到一個型別返回另一個型別的型別是型別構造子
  • 得到一個函式返回另一個函式的函式是高階函式
  • 型別類,和它們所提供的多型性,建立了一條很好的途徑,使我們認識到這樣的事實:在範疇論中事物經常被定義在一些物件之上

最後一條在本文中沒有強調,簡單說一下:我們可以看到fmap這個定義在Functor typeclass下的函式具有範疇上單一(多型)的概念,由不同的instance具體以不同實現,最後在使用者的程式碼中它的表象又是單一(多型)的,是我們在使用的時候思維在概念的層次。(也許可以對比物件導向中的介面)