Haskell 裡面的 Functor 是個什麼概念?

我知道c++裡面的functor的意思是一個有狀態的函數,不知道haskell里這是個什麼概念,我知道了fmap,但是還是沒明白什麼是functor


謝邀, @hongjiang引用的這篇文章寫的很不錯,只是用scala語言來描述Functor確實很啰嗦,遠沒有Haskell來的簡潔。下面就用Haskell來簡要的說一說吧。

Functor是什麼呢,從Haskell的編程實踐來說是一種數據結構,這種數據結構支持fmap函數,可以將操作基本數據類型的函數提升為可以操作這種數據結構的函數。比如將函數(+2)提升為將List中每個元素都加2的函數。這在有很多種複雜數據類型的情況下是很有用的。

從數學的範疇論來說是兩個範疇(Category)之間的態射(morphism),時常也稱為映射(下面為了方面會如此稱呼)。

這個態射有兩個部分,一個是範疇中對象間的映射fo,即將一種數據類型變換為另一種數據類型,在Haskell中是類型構造子。以List為例子, List就是範疇中對象間的映射fo,如下所示:

data List a = Nil | Cons a (List a)

另一個則是範疇中態射之間的映射fm,即將一個範疇中的態射變換為另一個範疇中的態射,在Haskell中就是fmap。以List為例子,List是Functor的一個實例,其範疇中態射之間的映射fm是fmap,因此有如下定義:

instance Functor List where
fmap = map

而在Haskell中,class Functor的定義如下:

class Functor f where
fmap :: (a -&> b) -&> f a -&> f b

也就是說,在Haskell中任何一種複雜數據類型(由其他簡單數據類型構造得到)F a只要滿足class Functor的定義要求,F就是一個Functor,比如上面的List a。

再舉一個例子Maybe a,其定義如下:

data Maybe a = Nothing | Just a

instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just a) = Just (f a)

其滿足class Functor的定義要求,因此Maybe是一個Functor。

當然,fmap要滿足如下條件,以滿足保持範疇的結構不變的要求。

fmap id = id
fmap (f . g) = fmap f . fmap g

最後用一句話來說,Functor就是範疇的範疇的態射(morphism),這個範疇的對象是範疇,態射是Functor。

再延伸一下,可以有Functor的範疇,這個範疇的對象是Functor,態射是自然變換。而Monad就是只有一個自函子對象的Functor範疇,用另一種常見的說法就是Monad只不過是自函子範疇上的幺半群。具體可參考我的另一個關於Monad的答案如何解釋 Haskell 中的單子?。


Functors are things that can be mapped over, like lists, Maybes, trees, and such.

Functors, Applicative Functors and Monoids


或許這篇對你有幫助:我所理解的monad(4):函子(functor)是什麼


我也來貢獻一個:

Functors, Applicatives, And Monads In Pictures

繪畫很萌,有 LYAH 風~


推薦一篇好文,圖文並茂,秒懂了 Functor, Applicative, 以及 Monad 三個概念,不敢獨享:Functors, Applicatives, And Monads In Pictures


推薦閱讀:

怎樣學習 haskell 效率比較高?
如何評價最新推出的 Glasgow Haskell Compiler (GHC) 8.0.1 版本?
haskell中的immutable array是如何實現隨機訪問的?
如何評價即將正式 release 的 GHC 8.2.1 ?
OCaml在寫編譯器上比Haskell好在哪?為何Rust第一個版本採用了OCaml?

TAG:函數式編程 | Haskell |