高级类类型就是使用其余类型构形成为一个新的类型,所以也称为 类型构造器(type constructors)。它的语法和高阶函数(higher-order functions)类似,高阶函数就是将其它函数做为参数的函数;高级类类型则是将构造类类型做为参数类型。一个高级类类型能够有一个或者多个类型做为参数。在Scala中,你可使用type关键字声明,以下:数组
type Callback[T] = Function1[T,Unit]
这里定义了一个高级类类型Callback,该类型接收一个类型 T,并构造一个新的类型Function1。类型Callback不是一个完整的类型,直到它实现了参数化。app
Function0,Function1,... 表示接收类型个数1,2,3,... ,如Function0[A],Function1[A,B]... ,一共23个FunctionX。用于定义匿名语法,实现语法糖。框架
高级类类型能够用于建立复杂类型,如M[N[T,X],Y],但能够看做更简单的类型,F[X]。ide
除了上面说的用关键字type定义的类型外,高级类类型最多见的实现是使用占位符代替。即F[_],在Scala中,占位符 _ 有特别的意义,能够表示任何东西。函数
如咱们要实现一个sum方法,该方法能够接收任何Scala集合类型,并实现加法处理。咱们可能实现的一种方式是,为全部集合类型定义相对应的方法:单元测试
def sumList(xs: List[Int]): Int = xs.foldLeft(0)(_ + _) def sumArray(xs: Array[Int]): Int = xs.foldLeft(0)(_ + _)
但这并非一个高效的函数实现,咱们要对全部集合类型进行抽象,以使得sum方法能够接收任何集合类型。所以,咱们要实现高级类类型。测试
trait Summable[A] { def plus(a1: A, a2: A): A def init: A }
如今,咱们分别为不一样的类型实现该特质:scala
object IntSummable extends Summable[Int] { override def plus(a1: Int, a2: Int): Int = a1 + a2 override def init: Int = 0 } object StringSummable extends Summable[String] { override def plus(a1: String, a2: String): String = a1 + a2 override def init: String = "" }
如今,咱们要为这个抽象的类类型,实现抽象的方法:code
trait Foldable[F[_]] { def foldLeft[A](xs: F[A], m: Summable[A]): A }
它接收全部集合类型,如今咱们为其实现具体的实现:three
object ListFoldLeft extends Foldable[List] { override def foldLeft[A](xs: List[A], m: Summable[A]): A = xs.foldLeft(m.init)(m.plus) } object ArrayFoldLeft extends Foldable[Array] { override def foldLeft[A](xs: Array[A], m: Summable[A]): A = xs.foldLeft(m.init)(m.plus) }
根据这个特质,咱们如今能够实现其通用的函数sum,该函数接收三个参数:集合、Foldable特质、Summable特质,以下:
def sum[F[_], A](xs: F[A], f: Foldable[F], m: Summable[A]): A = f.foldLeft(xs, m)
执行这个方法,打印输出:
logger.info(s"${sum(List(1, 2, 3), ListFoldLeft, IntSummable)}") logger.info(s"${sum(Array("one", "two", "three"), ArrayFoldLeft, StringSummable)}")
好了,咱们的高级类类型就已经实现了。可是等等,上面这个函数看起来很死板,我为何要接收三个参数呢,有没有sum(List(1,2,,3)) sum(Array("one", "two", "three"))这样的实现?有!
Scala有个强大的特性就是隐式调用,咱们须要实现这个sum函数的隐式调用,修改以下:
implicit val ListFoldable = new Foldable[List]{ override def foldLeft[A](xs: List[A], m: Summable[A]): A = xs.foldLeft(m.init)(m.plus) } implicit val ArrayFoldable = new Foldable[Array] { override def foldLeft[A](xs: Array[A], m: Summable[A]): A = xs.foldLeft(m.init)(m.plus) } implicit val IntSum = new Summable[Int] { override def plus(a1: Int, a2: Int): Int = a1 + a2 override def init: Int = 0 } implicit val StringSum = new Summable[String] { override def plus(a1: String, a2: String): String = a1 + a2 override def init: String = "" }
上面的写法实际上和下面是同价的:
implicit object ListFoldLeft extends Foldable[List] { override def foldLeft[A](xs: List[A], m: Summable[A]): A = xs.foldLeft(m.init)(m.plus) }
修改上述sum函数,让其只接收一个参数:
def sum[F[_]:Foldable,A:Summable](xs:F[A]) = { val c = implicitly[Foldable[F]] val d = implicitly[Summable[A]] c.foldLeft(xs,d) }
logger.info(s"${sum(List(1,2,3))}") logger.info(s"${sum(Array("one","two","three"))}")
SBT控制台执行上述代码,即可以获得相同的结果。
Scala的高级类类型颇有用,而且用途普遍,下面咱们看看一个Java Servlet到Scala Servlet的一个转换框架Scalaz。
Scalaz的核心部分很简单,该框架的核心就是实现了全部HTTP请求和响应的抽象。即,把全部的HTTP请求抽象为一个Request特质,全部响应也抽象为一个Response特质。咱们看看这个抽象实现的核心代码:
object Application { def application[IN[_], OUT[_]](f: Request[IN] => Response[OUT]) = new Application[IN,OUT] { def apply(implicit req: Request[IN]) = f(req) } }
没错,这里的Application,对应Java Servlet里面的application,其中IN[]和OUT[]的实现为Request[IN] => Response[OUT],即抽象请求处理后,返回抽象响应。这个方法实现了高级类类型(higher-kinded types),该方法实现了输入到输出的全部转换,这里的f函数为一个高阶函数实现。
经过高级类类型,结合高阶函数,函数组合,并结合相应的隐式转换和语法糖,Scalaz框架便由此诞生了!!