# 函数式非凡的抽象能力

``````//scala语言
def fold[A, B](l: MyList[A], z: B)(f: (A, B) => B):B = l match {
case Nil => z
case Cons(x, xs) => f(x, fold(xs, z)(f))
}复制代码``````
``````--haskell语言
foldr f zero (x:xs) = f x (foldr f zero xs)
foldr _ zero []     = zero复制代码``````

``````def createConnection(conn_url: Option[String],
conn_user: Option[String],
conn_pw: Option[String]): Option[Connection] =
for {
url <- conn_url
user <- conn_user
pw <- conn_pw
} yield DriverManager.getConnection(url, user, pw)复制代码``````

``(A, B, C): => D     转换为      (Option[A], Option[B], Option[C]) => Option[D]复制代码``

``````def lift[A, B, C, D](f: Function3[A, B, C, D]): Function3[Option[A], Option[B], Option[C], Option[D]] =
(oa: Option[A], ob: Option[B], oc: Option[C]) =>
for (a <- oa; b <- ob; c <- oc) yield f(a, b, c)复制代码``````

Function3事实上是Scala中对(A, B, C) => D函数的封装。相对而言，我更喜欢高阶函数的形式：

``````def lift[A, B, C, D](f: (A, B, C) => D): (Option[A], Option[B], Option[C]) => Option[D] =
(oa: Option[A], ob: Option[B], oc: Option[C]) =>
for (a <- oa; b <- ob; c <- oc) yield f(a, b, c)复制代码``````

lift函数是宽泛的抽象，之前的DriverManager.getConnection()函数则为一个具体的被转换对象。它可以作为参数传入到lift函数中：

``val createConnection1 = lift(DriverManager.getConnection)复制代码``

lift函数返回的实则是一个函数，它本质上等同于之前定义的createConnection()函数。由于lift抹掉了具体的类型信息，使得它不仅仅可以将getConnection提升为具有Option的函数，还能针对所有形如(A, B, C) => D格式的函数。让我们来自定义一个combine函数：

``````def combine(prefix: String, number: Int, suffix: String): String =
s"\$prefix - \$number - \$suffix"

val optionCombine = lift(combine)复制代码``````

``````def intDouble(rng: RNG): ((Int,Double), RNG)
def doubleInt(rng: RNG): ((Double,Int), RNG)
def double3(rng: RNG): ((Double,Double,Double), RNG)复制代码``````

``type Rand[+A] = RNG => (A, RNG)复制代码``