Scala类型系统——高级类类型(higher-kinded types)
高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors)。它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它函数作为参数的函数;高级类类型则是将构造类类型作为参数类型。一个高级类类型可以有一个或者多个类型作为参数。在Scala中,你可以使用type关键字声明,如下:
这里定义了一个高级类类型Callback,该类型接收一个类型 T,并构造一个新的类型Function1。类型Callback不是一个完整的类型,直到它实现了参数化。
Function0,Function1,... 表示接收类型个数1,2,3,... ,如Function0[A],Function1[A,B]... ,一共23个FunctionX。用于定义匿名语法,实现语法糖。
高级类类型可以用于创建复杂类型,如M[N[T,X],Y],但可以看作更简单的类型,F[X]。
Higher-kinded types
除了上面说的用关键字type定义的类型外,高级类类型最常见的实现是使用占位符代替。即F[_],在Scala中,占位符 _ 有特别的意义,可以表示任何东西。
User Story
如我们要实现一个sum方法,该方法可以接收任何Scala集合类型,并实现加法处理。我们可能实现的一种方式是,为所有集合类型定义相对应的方法:
但这并不是一个高效的函数实现,我们要对所有集合类型进行抽象,以使得sum方法可以接收任何集合类型。因此,我们要实现高级类类型。
现在,我们分别为不同的类型实现该特质:
现在,我们要为这个抽象的类类型,实现抽象的方法:
它接收所有集合类型,现在我们为其实现具体的实现:
根据这个特质,我们现在可以实现其通用的函数sum,该函数接收三个参数:集合、Foldable特质、Summable特质,如下:
执行这个方法,打印输出:
好了,我们的高级类类型就已经实现了。但是等等,上面这个函数看起来很死板,我为什么要接收三个参数呢,有没有sum(List(1,2,,3)) sum(Array("one", "two", "three"))这样的实现?有!
Scala有个强大的特性就是隐式调用,我们需要实现这个sum函数的隐式调用,修改如下:
上面的写法实际上和下面是同价的:
修改上述sum函数,让其只接收一个参数:
SBT控制台执行上述代码,便可以得到相同的结果。
Scala的高级类类型很有用,并且用途广泛,下面我们看看一个Java Servlet到Scala Servlet的一个转换框架Scalaz。
Scalaz核心实现
Scalaz的核心部分很简单,该框架的核心就是实现了所有HTTP请求和响应的抽象。即,把所有的HTTP请求抽象为一个Request特质,所有响应也抽象为一个Response特质。我们看看这个抽象实现的核心代码:
没错,这里的Application,对应Java Servlet里面的application,其中IN[]和OUT[]的实现为Request[IN] => Response[OUT],即抽象请求处理后,返回抽象响应。这个方法实现了高级类类型(higher-kinded types),该方法实现了输入到输出的所有转换,这里的f函数为一个高阶函数实现。
通过高级类类型,结合高阶函数,函数组合,并结合相应的隐式转换和语法糖,Scalaz框架便由此诞生了!!
https://my.oschina.net/Barudisshu/blog/690595
Scala类型系统——高级类类型(higher-kinded types)的更多相关文章
- Scalaz(30)- Free :Natural Tranformation ~> - map higher kinded types for free
当我们需要定义一些对应高阶类型进行相互类型转换的操作函数时,我们发现scala语言并不提供能定义这种函数的支持.举例来说:如果我们希望定义一个函数把对于任何T值的Option[T]转换成List[T] ...
- 【Scala类型系统】自身类型(self type)引用
定义 特质能够要求混入它的类扩展自还有一个类型,可是当使用自身类型(self type)的声明来定义特质时(this: ClassName =>).这种特质仅仅能被混入给定类型的子类其中. 如果 ...
- Java中的原始类型(Primitive Types)与引用类型(Reference Values)
Java虚拟机可以处理的类型有两种,一种是原始类型(Primitive Types),一种是引用类型(Reference Types). 与之对应,也存在有原始值(Primitive Values)和 ...
- 反射01 Class类的使用、动态加载类、类类型说明、获取类的信息
0 Java反射机制 反射(Reflection)是 Java 的高级特性之一,是框架实现的基础. 0.1 定义 Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对 ...
- Scala 深入浅出实战经典 第63讲:Scala中隐式类代码实战详解
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala函数---既存类型
语法: Type ::= InfixType ExistentialClauses ExistentialClauses ::= „forSome‟ „{‟ ExistentialDcl {semi ...
- Programming In Scala笔记-第十七章、Scala中的集合类型
本章主要介绍Scala中的集合类型,主要包括:Array, ListBuffer, Arraybuffer, Set, Map和Tuple. 一.序列 序列类型的对象中包含多个按顺序排列好的元素,可以 ...
- Programming In Scala笔记-第十一章、Scala中的类继承关系
本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...
- Scala学习(五)---Scala中的类
Scala中的类 摘要: 在本篇中,你将会学习如何用Scala实现类.如果你了解Java或C++中的类,你不会觉得这有多难,并且你会很享受Scala更加精简的表示法带来的便利.本篇的要点包括: 1. ...
随机推荐
- Java基础学习总结(36)——Java注释模板
代码注释是对代码设计者.代码阅读者以及系统间调用提供了有效的帮助,最大限度的提高团队开发合作效率增强系统的可维护性.我们追求简化,不是为了写注释而写注释. (快速使用请直接看六.七.八) 一.原则: ...
- 并行输入\输出控制器之我见(PIO)
中断信号FIQ及IRQ0到IRQn一般通过PIO控制器复用.但是,由于PIO控制器对于输入无效且中断线(FIQ或IRQ)仅作为输入,因此不必为中断分配I/0线. 电源管理控制器控制P ...
- HDU 4362
方程很简单 p[i][j] = min{dp[i-1][k] + |pos[i-1][k] - pos[i][k]|} + v[i][j]; 循环求值肯定TLE,主要是绝对值不方便.好吧,我真的BI了 ...
- 最小堆min_stack
class MinStack {public: void push(int x) { ele.push(x); if(min.empty()||x<=min.top()) // in or ...
- 【Allwinner ClassA20类库分析】4.GPIO类的使用
从本节起,開始使用ClassA20类库完毕操作外设的功能,请先在https://github.com/tjCFeng/ClassA20下载ClassA20类库. 封装的目的就是简化操作,试想一 ...
- CAS 4.0 配置开发手冊
1 下载 地址http://downloads.jasig.org/ cas-server-4.0.0-release.tar.gz cas-client-3.3.3-release.tar.g ...
- job调度时间格式
*/5 * * * * ?---------------每隔5秒执行一次0 */1 * * * ?---------------每隔1分钟执行一次0 0 23 * * ?--------------- ...
- Openfire 配置连接SQL SERVER(非默认实例)
安装好Openfire之后,紧接着进行配置. 连接数据库的时候遇上问题. 打算用我本机上的一个SQL SERVER做为数据库.但是,我本机装了几个SQL SERVER实例,现在我打算使用的是那个非默认 ...
- Mongo-JS-导出数据为insert语句
======2014-11-14 数据提取======= [query@query-server hurl]$ cat test.sh tlist=`cat ./username.txt`; for ...
- vsftpd出现“Response: 500 OOPS: cannot change directory”解决方法(转载)
vsftpd出现“Response: 500 OOPS: cannot change directory”解决方法 笔者用的Linux发行版本为centos当用FTP客户端连接时,出现如下错误提示 ...