Functor与fmap
2015-11-06 11:41
169 查看
一.
Functor俗称仿函数或者函子,他是一个类型类,我们先看看他的结构
可以看出它是一个类型构造器的构造器,但是不像List等序列(强调的是容器),我们这里X并不是像F容器,我们可以把X看作action集合,所以我猜他才被称呼为Functor的
Functor里最重要的部分就是map的函数了
我们必须理解Functor中的map是做了什么事情,而且必须熟悉,不然后面更加抽象的就无法理解了(当然即使你理解这个后,后面的不一定能理解,后面会更加抽象!)
我们先看看我们以前熟悉的map
或许你认为该map与上面的一样,当然意义是一样的,但是结果是不一样的,这里我们的map返回的依旧是原本的序列
而上面的并不是返回一个Functor,他返回的只是当初的一个容器类,也即是F[_](所以他才叫做函子)
具备函数的特性:
好了,上面我们是通过字面意识来理解Functor的,下面我们以Functor的真正意义来理解吧
1.Functor是个lift过程
什么样的lift呢?
我们举个例子:
(1).我们有n个元素
val a = 1,2,3,4(我们只是打比方,实际没有这个语法)
如果我们要对a执行一个加一操作,那么我们必须编写一个函数,如
def fun:Int => Int = _ + 1
这样是符合的,因为a就是int类型!
(2).如果a是个序列呢?
val a = List(1,2,3)
必然是
def fun:List[Int] => List[Int]
我们从一个裸体的Int到包装的List型的fn,这是个lift过程,这就是functor的工作了
2.对1部分的总结
lift就是把函数的映射"映射"到另一个映射中
从而我们才可以对F[_]的类型的数据进行操作
3.使用
上面我已经解析的够清楚了,至少个人觉得比我看的资料没那么抽象了
估计有人说,以上的操作不是直接使用
List(1,2,3,4) map {_ + 1}就可以完成了吗?如果你这么觉得的话就得好好看monad了
这里我在废话讲解一下吧,不然如果你还是不懂那么就无法下去了
首先map接受一个Int => Int的函数,然而(1,2,3)并不是int
所以(1,2,3)通过隐式的Functor将Int => Int 提升(Int, Int, Int) => (Int, Int, Int)
从而才能计算
二.
上面把基本的讲解了,而Functor的操作似乎可以直接通过F[_]的成员函数操作,而不必通过X的lift过程.好像是这样吧,下面我们就进入另一个------------------------
操作对象是函数,当然核心lift还是不变的
这回你知道Functor的意义了吧,他不仅通过lift对元素或者容器进行操作,他甚至可以对函数进行操作
他把
Int => Int
提升为
func => func
三.
与fmap的区别,顺序的区别
但是两个都是lift的使用(原理一样)
看看签名
而我们的map是
F.map(a->b)
翻译成
(F a) -> (F b)
从Functor角度看只是实现的方式不同,原理一样.再次强调
----都是lift的使用
然后
看看Functor的其他操作
四.
应用式,如果你理解了上面的内容了,那么就看这篇介绍应用式(自已就懒得敲了)
http://eed3si9n.com/learning-scalaz/Applicative.html
Functor俗称仿函数或者函子,他是一个类型类,我们先看看他的结构
scala> :kind Functor scalaz.Functor's kind is X[F[A]]
可以看出它是一个类型构造器的构造器,但是不像List等序列(强调的是容器),我们这里X并不是像F容器,我们可以把X看作action集合,所以我猜他才被称呼为Functor的
Functor里最重要的部分就是map的函数了
/** Lift `f` into `F` and apply to `F[A]`. */ def map[A, B](fa: F[A])(f: A => B): F[B]
我们必须理解Functor中的map是做了什么事情,而且必须熟悉,不然后面更加抽象的就无法理解了(当然即使你理解这个后,后面的不一定能理解,后面会更加抽象!)
我们先看看我们以前熟悉的map
scala> List(1,2,3) map { _ + 1} res5: List[Int] = List(2, 3, 4)
或许你认为该map与上面的一样,当然意义是一样的,但是结果是不一样的,这里我们的map返回的依旧是原本的序列
而上面的并不是返回一个Functor,他返回的只是当初的一个容器类,也即是F[_](所以他才叫做函子)
具备函数的特性:
scala> def a:Int=>Int = a => a + 1 a: Int => Int scala> :kind a scala.Function1's kind is F[-A1,+A2] scala> :kind a(1) scala.Int's kind is A scala>
好了,上面我们是通过字面意识来理解Functor的,下面我们以Functor的真正意义来理解吧
1.Functor是个lift过程
什么样的lift呢?
我们举个例子:
(1).我们有n个元素
val a = 1,2,3,4(我们只是打比方,实际没有这个语法)
如果我们要对a执行一个加一操作,那么我们必须编写一个函数,如
def fun:Int => Int = _ + 1
这样是符合的,因为a就是int类型!
(2).如果a是个序列呢?
val a = List(1,2,3)
必然是
def fun:List[Int] => List[Int]
我们从一个裸体的Int到包装的List型的fn,这是个lift过程,这就是functor的工作了
2.对1部分的总结
lift就是把函数的映射"映射"到另一个映射中
从而我们才可以对F[_]的类型的数据进行操作
3.使用
上面我已经解析的够清楚了,至少个人觉得比我看的资料没那么抽象了
估计有人说,以上的操作不是直接使用
List(1,2,3,4) map {_ + 1}就可以完成了吗?如果你这么觉得的话就得好好看monad了
scala> (1, 2, 3) map {_ + 1} res7: (Int, Int, Int) = (1,2,4)
这里我在废话讲解一下吧,不然如果你还是不懂那么就无法下去了
首先map接受一个Int => Int的函数,然而(1,2,3)并不是int
所以(1,2,3)通过隐式的Functor将Int => Int 提升(Int, Int, Int) => (Int, Int, Int)
从而才能计算
二.
上面把基本的讲解了,而Functor的操作似乎可以直接通过F[_]的成员函数操作,而不必通过X的lift过程.好像是这样吧,下面我们就进入另一个------------------------
操作对象是函数,当然核心lift还是不变的
scala> (((x: Int) => x + 1) map {_ * 7}) res8: Int => Int = <function1> scala> res8(12) res9: Int = 91 scala> res8(1) res10: Int = 14
这回你知道Functor的意义了吧,他不仅通过lift对元素或者容器进行操作,他甚至可以对函数进行操作
他把
Int => Int
提升为
func => func
三.
与fmap的区别,顺序的区别
但是两个都是lift的使用(原理一样)
看看签名
fmap :: (a -> b) -> f a -> f b
而我们的map是
F.map(a->b)
翻译成
(F a) -> (F b)
从Functor角度看只是实现的方式不同,原理一样.再次强调
----都是lift的使用
然后
看看Functor的其他操作
scala> List(1, 2, 3) >| "x" res47: List[String] = List(x, x, x) scala> List(1, 2, 3) as "x" res48: List[String] = List(x, x, x) scala> List(1, 2, 3).fpair res49: List[(Int, Int)] = List((1,1), (2,2), (3,3)) scala> List(1, 2, 3).strengthL("x") res50: List[(String, Int)] = List((x,1), (x,2), (x,3)) scala> List(1, 2, 3).strengthR("x") res51: List[(Int, String)] = List((1,x), (2,x), (3,x)) scala> List(1, 2, 3).void res52: List[Unit] = List((), (), ())
四.
应用式,如果你理解了上面的内容了,那么就看这篇介绍应用式(自已就懒得敲了)
http://eed3si9n.com/learning-scalaz/Applicative.html
相关文章推荐
- 时间与日期处理
- ajax中erro调试错误信息
- 计算机视觉,模式识别,机器学习,相关网站
- shell编程-进入某个目录将目录下面的文件名存入数组
- 使用Intent.ACTION_EDIT 调用系统编辑联系人
- jQuery统计数字不停的滚动最后停止
- anroid USB类设备无法自动生成节点解决
- 借贷宝的使用方法
- linux安装中文输入法
- MySQL 4.表操作与列操作
- GeooyMenu 设置一开始不显示
- MySQL:Table XXX is marked as crashed and should be repaired
- 黑马程序员---自学随堂笔记----网络编程
- linux信号
- 设计模式一:观察者模式的自我实现
- find -exec 命令总是报缺参数错误
- Android开发&多媒体控件
- masonry的简单使用
- js读txt
- 面试深度问题