# 函数式非凡的抽象能力

//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)


posted @ 2016-03-31 10:06  张逸  阅读(2224)  评论(6编辑  收藏  举报