zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Scalaz(5)- typeclass:my typeclass scalaz style-demo

my Demo Style Scalaz
2023-09-14 08:57:58 时间

 我们在上一篇讨论中介绍了一些基本的由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)

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放一个默认隐式转换:


object NonZero {

 def create[A](f: A = Boolean): NonZero[A] = new NonZero[A] {

 def nonZero(a: A): Boolean = f(a)

 implicit val intNZInstance: NonZero[Int] = create {

 case 0 = false

 case _ = true

}

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

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


1 import ToNonZeroOps._

3 10.isNonZero // res0: Boolean = true

4 0.isNonZero // res1: Boolean = false

5 2.isNonZero // res2: Boolean = true

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


import ToNonZeroOps._

implicit val stringNZInstance: NonZero[String] = NonZero.create {

 case "" = false

 case _ = true

} // stringNZInstance : scalaz.ex5.NonZero[String] = scalaz.ex5$NonZero$$anon$1@

 //| 1c655221

implicit val booleanNZInstance: NonZero[Boolean] = NonZero.create { b = b }

 // booleanNZInstance : scalaz.ex5.NonZero[Boolean] = scalaz.ex5$NonZero$$anon$

 //| 1@6aaa5eb0

implicit def listNZInstance[A]: NonZero[List[A]] = NonZero.create {

 case Nil = false

 case _ = true

} // listNZInstance: [A]= scalaz.ex5.NonZero[List[A]]

"".isNonZero // res0: Boolean = false

"not empty".isNonZero // res1: Boolean = true

true.isNonZero // res2: Boolean = true

false.isNonZero // res3: Boolean = false

List(1,2,3).isNonZero // res4: Boolean = true

List("a","b").isNonZero // res5: Boolean = true

List().isNonZero // res6: Boolean = false


2.isNonZero // res9: Boolean = true

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


trait NonZero[A] {

 def nonZero(a: A): Boolean

object NonZero {

 def create[A](f: A = Boolean): NonZero[A] = new NonZero[A] {

 def nonZero(a: A): Boolean = f(a)

 implicit val intNZInstance: NonZero[Int] = create {

 case 0 = false

 case _ = true

class NonZeroOps[A](a: A)(implicit ev: NonZero[A]) {

 def isNonZero: Boolean = ev.nonZero(a)

object ToNonZeroOps {

 implicit def toNonZeroOps[A](a: A)(implicit ev: NonZero[A]) = new NonZeroOps[A](a)

import ToNonZeroOps._

implicit val stringNZInstance: NonZero[String] = NonZero.create {

 case "" = false

 case _ = true

} // stringNZInstance : scalaz.ex5.NonZero[String] = scalaz.ex5$NonZero$$anon$1@

 //| 1c655221

implicit val booleanNZInstance: NonZero[Boolean] = NonZero.create { b = b }

 // booleanNZInstance : scalaz.ex5.NonZero[Boolean] = scalaz.ex5$NonZero$$anon$

 //| 1@6aaa5eb0

implicit def listNZInstance[A]: NonZero[List[A]] = NonZero.create {

 case Nil = false

 case _ = true

} // listNZInstance: [A]= scalaz.ex5.NonZero[List[A]]

"".isNonZero // res0: Boolean = false

"not empty".isNonZero // res1: Boolean = true

true.isNonZero // res2: Boolean = true

false.isNonZero // res3: Boolean = false

List(1,2,3).isNonZero // res4: Boolean = true

List("a","b").isNonZero // res5: Boolean = true

List().isNonZero // res6: Boolean = false


Problem Description Function Fx,yF_{x,y}satisfies: F1,1=F1,2=1F_{1,1}=F_{1,2}=1F1,i=F1,i−1...