高級類類型就是使用其餘類型構形成爲一個新的類型,所以也稱爲 類型構造器(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框架便由此誕生了!!