Scalaz（3）－ 基础篇：函数概括化－Generalizing Functions

0
0
1
1. 云栖社区>
2. 博客>
3. 正文

## Scalaz（3）－ 基础篇：函数概括化－Generalizing Functions

Scalaz是个通用的函数式编程组件库。它提供的类型、函数组件都必须具有高度的概括性才能同时支持不同数据类型的操作。可以说，scalaz提供了一整套所有编程人员都需要的具有高度概括性的通用函数，它是通过随意多态（ad-hoc polymorphism）来帮助用户使用这些函数的。随意多态就是trait+implicit parameters+implicit conversions。简单的说就是scalaz提供一个概括化的函数，用户可以在各种类型上施用这个同一函数。概括化（generalizing）函数最基本的技巧应该是类型参数变量（parametric type variable）的使用了。如下：

``````1 def head[T](xs: List[T]): T = xs(0)               //> head: [T](xs: List[T])T
2 head(List(1,2,3,4))                               //> res0: Int = 1
3 head(List("a","b","c"))                           //> res1: String = a
4 case class Car(manu: String)
5 head(Car("Honda") :: Car("Toyota") :: Nil)        //> res2: scalaz.learn.ex2.Car = Car(Honda)``````

``````def sum(xs: List[Int]): Int = xs.foldLeft(0){_ + _}
//> sum: (xs: List[Int])Int
sum(List(1,2,3))                                  //> res0: Int = 6
//你不能这样：sum(List(1.0,2.0,3.0)``````

``````object intMonoid {
def mappend(i1: Int, i2: Int): Int = i1 + i2
def mzero = 0
}
def sum(xs: List[Int]): Int = xs.foldLeft(intMonoid.mzero)(intMonoid.mappend)
//> sum: (xs: List[Int])Int
sum(List(1,2,3))                                  //> res0: Int = 6``````

``````object stringMonoid {
def mappend(s1: String, s2: String): String = s1 + s2
def mzero = ""
}
def sum(xs: List[String]): String = xs.foldLeft(stringMonoid.mzero)(stringMonoid.mappend)
//> sum: (xs: List[String])String
sum(List("Hello,"," how are you"))                //> res0: String = Hello, how are you``````

``````1 trait Monoid[A] {
2     def mappend(a1: A, a2: A): A
3     def mzero: A
4 }``````

``````trait Monoid[A] {
def mappend(a1: A, a2: A): A
def mzero: A
}
object intMonoid extends Monoid[Int]{
def mappend(i1: Int, i2: Int): Int = i1 + i2
def mzero = 0
}
object stringMonoid extends Monoid[String]{
def mappend(s1: String, s2: String): String = s1 + s2
def mzero = ""
}``````

``````1 def sum[A](xs: List[A])(m: Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
2                                                   //> sum: [A](xs: List[A])(m: scalaz.learn.ex2.Monoid[A])A
3 sum(List(1,2,3))(intMonoid)                       //> res0: Int = 6
4 sum(List("Hello,"," how are you"))(stringMonoid)  //> res1: String = Hello, how are you``````

``````trait Monoid[A] {
def mappend(a1: A, a2: A): A
def mzero: A
}
implicit object intMonoid extends Monoid[Int]{
def mappend(i1: Int, i2: Int): Int = i1 + i2
def mzero = 0
}
implicit object stringMonoid extends Monoid[String]{
def mappend(s1: String, s2: String): String = s1 + s2
def mzero = ""
}
def sum[A](xs: List[A])(implicit m: Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
//> sum: [A](xs: List[A])(implicit m: scalaz.learn.ex2.Monoid[A])A
sum(List(1,2,3))                                  //> res0: Int = 6
sum(List("Hello,"," how are you"))                //> res1: String = Hello, how are you``````

``````trait Monoid[A] {
def mappend(a1: A, a2: A): A
def mzero: A
}
object Monoid {
implicit object intMonoid extends Monoid[Int]{
def mappend(i1: Int, i2: Int): Int = i1 + i2
def mzero = 0
}
implicit object stringMonoid extends Monoid[String]{
def mappend(s1: String, s2: String): String = s1 + s2
def mzero = ""
}
}``````

``````1 object listFoldLeft {
2     def foldLeft[A,B](xs: List[A])(b: B)(f:(B,A) => B):B = xs.foldLeft(b)(f)
3 }
4 def sum[A](xs: List[A])(implicit m: Monoid[A]): A = listFoldLeft.foldLeft(xs)(m.mzero)(m.mappend)
5                                                   //> sum: [A](xs: List[A])(implicit m: scalaz.learn.ex2.Monoid[A])A``````

``````trait FoldLeft[M[_]] {
def foldLeft[A,B](xs: M[A])(b: B)(f: (B,A) => B): B
}
object FoldLeft {
implicit object listFoldLeft extends FoldLeft[List] {
def foldLeft[A,B](xs: List[A])(b: B)(f:(B,A) => B):B = xs.foldLeft(b)(f)
}
}
def sum[M[_],A](xs: M[A])(implicit m: Monoid[A], fl: FoldLeft[M]): A =
fl.foldLeft(xs)(m.mzero)(m.mappend)            //> sum: [M[_], A, B](xs: M[A])(implicit m: scalaz.learn.ex2.Monoid[A], implicit
//|  fl: scalaz.learn.ex2.FoldLeft[M])A
sum(List(1,2,3))                                  //> res0: Int = 6
sum(List("Hello,"," how are you"))                //> res1: String = Hello, how are you``````

``````1 def sum1[A: Monoid, M[_]: FoldLeft](xs: M[A]): A = {
2     val m = implicitly[Monoid[A]]
3     val fl = implicitly[FoldLeft[M]]
4     fl.foldLeft(xs)(m.mzero)(m.mappend)
5 }                                                 //> sum1: [A, M[_]](xs: M[A])(implicit evidence\$1: scalaz.learn.ex2.Monoid[A], i
6                                                   //| mplicit evidence\$2: scalaz.learn.ex2.FoldLeft[M])A``````

``````1 def plus[A: Monoid](a1: A, a2: A): A = implicitly[Monoid[A]].mappend(a1,a2)
2                                                   //> plus: [A](a1: A, a2: A)(implicit evidence\$3: scalaz.learn.ex2.Monoid[A])A
3 plus(1,2)                                         //> res2: Int = 3
4 plus("hello ","world")                            //> res3: String = hello world``````

``````1 trait MonoidOp[A]{
2     val M : Monoid[A]
3     val a1: A
4     def |+|(a2: A) = M.mappend(a1,a2)
5 }``````

``````trait MonoidOp[A]{
val M : Monoid[A]
val a1: A
def |+|(a2: A) = M.mappend(a1,a2)
}
implicit def toMonoidOp[A: Monoid](a: A) = new MonoidOp[A] {
val M = implicitly[Monoid[A]]
val a1 = a
}                                                 //> toMonoidOp: [A](a: A)(implicit evidence\$3: scalaz.learn.ex2.Monoid[A])scala
//| z.learn.ex2.MonoidOp[A]
1 |+| 2                                           //> res2: Int = 3
"hello " |+| "world"                              //> res3: String = hello world``````

+ 关注