Functors 函子
前言
以下是從
- 魔力 Haskell
- Haskell Typeclassopedia
擷取出的程式碼和我自己的理解,如有錯誤還請海涵並告知
最近在看 Haskell,純 function 的設計和其他語言很不一樣,滿有趣的,但 Monad 的概念真的不是很好懂。 Monads 是 Applicative Functors,Applicative Functors 是 Functor,所以決定從 Functor 開始記。
所以總共會有三篇文章 :
WHAT I WISH I KNEW WHEN LEARNING HASKELL 推薦從 Haskell typesystem 看起,接著是 Typeclassopedia,讀關於 Monad 的定義,並且不要讀 Monad 的 tutorial,不要寫關於 Monad 的類比或比喻,並且實際把 Monad 用在 code 中。
定義
Prelude> :i Functor
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
(<$) :: a -> f b -> f a
{-# MINIMAL fmap #-}
-- Defined in ‘GHC.Base’
(下面還有 instances 的部分,例如 Maybe, [ ] 等,這裡先拿掉)
Functor instances 必須實作 fmap,fmap 的 type signature 是 (a -> b) -> f a -> f b
,可以把他看成接收一個 a -> b
的普通函數,並把它提升成 f a -> f b
f 是什麼
f
不是像 Int
一樣 concrete 的 type,他是 type constructor,需要一個 type 作為他的參數。f 的 kind 是 * -> *
,舉例來說,Maybe
的 kind 就是 * -> *
。Maybe
本身不是一種 type,但 Maybe Int
是
fmap
fmap
applies a function to each element of a container, without altering the structure of the container
(>$)
Finally, we can understand (<$): instead of applying a function to the values a container/context, it simply replaces them with a given value. This is the same as applying a constant function, so (<$) can be implemented in terms of fmap.
常見的 Functor instances
- Maybe
- Either
- IO
Functor Laws
fmap id = id
fmap (g . h) = (fmap g) . (fmap h)
第一條說把 identity function map 到容器裡的每個元素沒有影響
第二條則是把兩個 function 的 composition map 過去,和先 map 一個 function,再 map 另一個,結果要是一樣的。
編譯器不會主動檢查這些規則,我們必須自己注意。
-- Evil Functor instance
instance Functor [] where
fmap :: (a -> b) -> [a] -> [b]
fmap _ [] = []
fmap g (x:xs) = g x : g x : fmap g xs
a = [1..3]
fmap' id a == id a
Haskell Wiki: Category_theory/Functor
參考
You Could Have Invented Monads! (And Maybe You Already Have.)
參考資料
https://wiki.haskell.org/Typeclassopedia
http://dev.stephendiehl.com/hask/#functors
https://sovmedcare.github.io/archives/
https://hackage.haskell.org/package/base-4.11.0.0/docs/src/GHC.Base.html#Functor