[Haskell] Functor

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

其中f并不是一个具体类型,而是一个单参类型构造器:k f = * -> *)。
类型f a的值称为functor value。
<u></u>fmap接受一个普通函数a -> b,返回一个functor value上的函数f a -> f b

Functor Law
只是Functor类型类的实例,还不是一个数学意义上的Functor,需要满足以下定律。
(1)fmap id = id
(2)fmap (f . g) = fmap f . fmap g

Examples

(1)[]是Functor类型类的实例

instance Functor [] where
fmap = map 

列表类型上的map就是fmap

map :: (a -> b) -> [a] -> [b]

注:
不能写“instance Functor [a] where”而要写“[]” (:k [] = * -> *),因为Functor类型类的实例必须是一个单参类型构造器,而“[a]”是一个具体类型。

(2)Maybe是Functor类型类的实例

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

其中,Maybe类型的定义如下:

data Maybe a = Just a | Nothing

其中,fmap :: (a -> b) -> Maybe a -> Maybe b

(3)Tree是Functor类型类的实例

instance Functor Tree where
fmap f EmptyTree = EmptyTree
fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right)

其中,Tree类型的定义如下:

data Tree a = EmptyTree | Node a (Tree a) (Tree a)

(4)Either a是Functor类型类的实例

<u></u>Either a b是一个具体类型,而Functor类型类的实例必须是单参类型构造器。
而Either是接受两个参数的类型构造器(:k Either = * -> * -> *),也不可以。
部分应用Either的一个参数类型,得到Either a,它是一个单参类型构造器了(:k Either a = * -> *)。

instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x

其中,Either类型的定义如下:

data Either a b = Left a | Right b

(5)(->) r是Functor类型类的实例

函数类型r -> a可以改写为:(->) r a,则“->”就是一个接受两个参数的类型构造器了(:k (->) = * -> * -> *)。
如果已提供一个类型参数,则“(->) r”就是单参类型构造器了(:k (-> r) = * -> *),可以作为Functor类型类的实例了。其中,(->) r = (r ->)

instance Functor ((->) r) where
fmap f g = (\x -> f (g x))

我们考虑一下fmap的类型是如何实例化的

fmap :: (a -> b) -> f a -> f b
= (a -> b) -> ((->) r a) -> ((->) r b) 
= (a -> b) -> (r -> a) -> (r -> b)

而这正好是函数复合“.”的类型,所以fmap还可以定义为:

instance Functor ((->) r) where
fmap = (.)

因此,fmap作用在两个函数上面,就相当于进行函数复合。

ghci> fmap (* 3) (+ 100) 1
303

还可以有不同的写法:

fmap (* 3) (+ 100) 1
= (* 3) `fmap` (+ 100) $ 1
= (* 3) . (+ 100) $ 1
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,537评论 0 17
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile丽语阅读 3,865评论 0 6
  • 123.继承 一个类可以从另外一个类继承方法,属性和其他特征。当一个类继承另外一个类时, 继承类叫子类, 被继承的...
    无沣阅读 1,436评论 2 4
  • 好久没有写文章了,不出意外,过去的这几个月一直在边实习,边准备秋招的状态中。 加入秋招大军 说实话,从一开始我就清...
    凌枫同学阅读 426评论 3 0
  • 有的人见一面便会觉得好舒服,有的人认识了几年,见面也只是尴尬的寒暄几句。 人与人之间一定是有磁场的吧,脾气,性格,...
    清泽阅读 295评论 0 3