zoukankan      html  css  js  c++  java
  • Scalaz(5)- typeclass:my typeclass scalaz style-demo

      我们在上一篇讨论中介绍了一些基本的由scalaz提供的typeclass。这些基本typeclass主要的作用是通过操作符来保证类型安全,也就是在前期编译时就由compiler来发现错误。在这篇讨论中我希望能按照scalaz的格式设计自己的typeclass并能使之融入scalaz库结构里去。

      我们来设计一个NoneZero typeclass。这个NoneZero typeclass能确定目标类型值是否为空,如:

    0.nonZero = false

    3.nonZero = true

    "".nonZero = false

    "value".nonZero = true

    List().nonZero = false

    List(1,2,3).nonZero = true

    首先是trait: (定义typeclass行为)

    1 trait NonZero[A] {
    2   def nonZero(a: A): Boolean
    3 }

    现在NonZero typeclass只有一项功能或行为,就是这个抽象函数NonZero:对任何类型A值a,返回Boolean结果。

    为了方便使用NoneZero typeclass,我们在伴生对象里定义NonZero[A]的构建函数,这样我们就不需要每次都重新实现抽象行为函数nonZero了:

    1 object NonZero {
    2     def create[A](f: A => Boolean): NonZero[A] = new NonZero[A] {
    3         def nonZero(a: A): Boolean = f(a)
    4     }
    5 }

    只要我们提供一个f: A => Boolean函数就能用create来构建一个NonZero[A]实例。实际上这个f函数定义了类型A在NonZero tyoeclass中的具体行为。

    下一步是注入操作方法:

    1 class NonZeroOps[A](a: A)(implicit ev: NonZero[A]) {
    2     def isNonZero: Boolean = ev.nonZero(a)
    3 }

    我们注入了一个操作方法isNonZero。注意:注入方法是针对所有类型A的,所以需要NonZero[A]作为参数。

    跟着就是隐式作用域解析了(implicit resolution):

    1 object ToNonZeroOps {
    2     implicit def toNonZeroOps[A](a: A)(implicit ev: NonZero[A]) = new NonZeroOps[A](a)
    3 }

    这是一个隐式视域(implicit view):从类型A转换到NonZeroOps[A]。这样类型A就具备isNonZero这个操作方法了。

    我们按scalaz惯例在object NonZero放一个默认隐式转换:

    1 object NonZero {
    2     def create[A](f: A => Boolean): NonZero[A] = new NonZero[A] {
    3         def nonZero(a: A): Boolean = f(a)
    4     }
    5     implicit val intNZInstance: NonZero[Int] = create {
    6         case 0 => false
    7         case _ => true
    8      }
    9 }

    注意我们在create参数里使用了partial function。

    然后试试在Int类型上使用:

    1 import ToNonZeroOps._
    2 
    3 10.isNonZero                                      //> res0: Boolean = true
    4 0.isNonZero                                       //> res1: Boolean = false
    5 2.isNonZero                                       //> res2: Boolean = true

    不错,已经可以用了。再试试其它即兴类型:

     1 import ToNonZeroOps._
     2 implicit val stringNZInstance: NonZero[String] = NonZero.create {
     3   case "" => false
     4   case _ => true
     5 }                                                 //> stringNZInstance  : scalaz.ex5.NonZero[String] = scalaz.ex5$NonZero$$anon$1@
     6                                                   //| 1c655221
     7 implicit val booleanNZInstance: NonZero[Boolean] = NonZero.create { b => b }
     8                                                   //> booleanNZInstance  : scalaz.ex5.NonZero[Boolean] = scalaz.ex5$NonZero$$anon$
     9                                                   //| 1@6aaa5eb0
    10 
    11 implicit def listNZInstance[A]: NonZero[List[A]] = NonZero.create {
    12     case Nil => false
    13     case _ => true
    14 }                                                 //> listNZInstance: [A]=> scalaz.ex5.NonZero[List[A]]
    15 
    16 "".isNonZero                                      //> res0: Boolean = false
    17 "not empty".isNonZero                             //> res1: Boolean = true
    18 true.isNonZero                                    //> res2: Boolean = true
    19 false.isNonZero                                   //> res3: Boolean = false
    20 List(1,2,3).isNonZero                             //> res4: Boolean = true
    21 List("a","b").isNonZero                           //> res5: Boolean = true
    22 List().isNonZero                                  //> res6: Boolean = false
    23 
    24 
    25 
    26 10.isNonZero                                      //> res7: Boolean = true
    27 0.isNonZero                                       //> res8: Boolean = false
    28 2.isNonZero                                       //> res9: Boolean = true

    我把完整的代码贴在下面吧,供大家练习参考:

     1 trait NonZero[A] {
     2     def nonZero(a: A): Boolean
     3 }
     4 object NonZero {
     5     def create[A](f: A => Boolean): NonZero[A] = new NonZero[A] {
     6         def nonZero(a: A): Boolean = f(a)
     7     }
     8     implicit val intNZInstance: NonZero[Int] = create {
     9         case 0 => false
    10         case _ => true
    11      }
    12 }
    13 class NonZeroOps[A](a: A)(implicit ev: NonZero[A]) {
    14     def isNonZero: Boolean = ev.nonZero(a)
    15 }
    16 object ToNonZeroOps {
    17     implicit def toNonZeroOps[A](a: A)(implicit ev: NonZero[A]) = new NonZeroOps[A](a)
    18 }
    19 
    20 import ToNonZeroOps._
    21 implicit val stringNZInstance: NonZero[String] = NonZero.create {
    22   case "" => false
    23   case _ => true
    24 }                                                 //> stringNZInstance  : scalaz.ex5.NonZero[String] = scalaz.ex5$NonZero$$anon$1@
    25                                                   //| 1c655221
    26 implicit val booleanNZInstance: NonZero[Boolean] = NonZero.create { b => b }
    27                                                   //> booleanNZInstance  : scalaz.ex5.NonZero[Boolean] = scalaz.ex5$NonZero$$anon$
    28                                                   //| 1@6aaa5eb0
    29 
    30 implicit def listNZInstance[A]: NonZero[List[A]] = NonZero.create {
    31     case Nil => false
    32     case _ => true
    33 }                                                 //> listNZInstance: [A]=> scalaz.ex5.NonZero[List[A]]
    34 
    35 "".isNonZero                                      //> res0: Boolean = false
    36 "not empty".isNonZero                             //> res1: Boolean = true
    37 true.isNonZero                                    //> res2: Boolean = true
    38 false.isNonZero                                   //> res3: Boolean = false
    39 List(1,2,3).isNonZero                             //> res4: Boolean = true
    40 List("a","b").isNonZero                           //> res5: Boolean = true
    41 List().isNonZero                                  //> res6: Boolean = false
    42 
    43 
    44 
    45 10.isNonZero                                      //> res7: Boolean = true
    46 0.isNonZero                                       //> res8: Boolean = false
    47 2.isNonZero                                       //> res9: Boolean = true
  • 相关阅读:
    Applet
    Tutorial中代码的区别及不同效果
    Session
    代码解析&Filter用户授权例子
    Web的后台运作过程
    XML
    数据库
    spring常用注解
    spring mvc 常用注解
    @requestMapping
  • 原文地址:https://www.cnblogs.com/tiger-xc/p/4821819.html
Copyright © 2011-2022 走看看