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行为)
trait NonZero[A] {
def nonZero(a: A): Boolean
}
现在NonZero typeclass只有一项功能或行为,就是这个抽象函数NonZero:对任何类型A值a,返回Boolean结果。
为了方便使用NoneZero typeclass,我们在伴生对象里定义NonZero[A]的构建函数,这样我们就不需要每次都重新实现抽象行为函数nonZero了:
object NonZero {
def create[A](f: A => Boolean): NonZero[A] = new NonZero[A] {
def nonZero(a: A): Boolean = f(a)
}
}
只要我们提供一个f: A => Boolean函数就能用create来构建一个NonZero[A]实例。实际上这个f函数定义了类型A在NonZero tyoeclass中的具体行为。
下一步是注入操作方法:
class NonZeroOps[A](a: A)(implicit ev: NonZero[A]) {
def isNonZero: Boolean = ev.nonZero(a)
}
我们注入了一个操作方法isNonZero。注意:注入方法是针对所有类型A的,所以需要NonZero[A]作为参数。
跟着就是隐式作用域解析了(implicit resolution):
object ToNonZeroOps {
implicit def toNonZeroOps[A](a: A)(implicit ev: NonZero[A]) = new NonZeroOps[A](a)
}
这是一个隐式视域(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 => false
case _ => true
}
}
注意我们在create参数里使用了partial function。
然后试试在Int类型上使用:
import ToNonZeroOps._ .isNonZero //> res0: Boolean = true
.isNonZero //> res1: Boolean = false
.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(,,).isNonZero //> res4: Boolean = true
List("a","b").isNonZero //> res5: Boolean = true
List().isNonZero //> res6: Boolean = false .isNonZero //> res7: Boolean = true
.isNonZero //> res8: Boolean = false
.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 => 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(,,).isNonZero //> res4: Boolean = true
List("a","b").isNonZero //> res5: Boolean = true
List().isNonZero //> res6: Boolean = false
.isNonZero //> res7: Boolean = true
.isNonZero //> res8: Boolean = false
.isNonZero //> res9: Boolean = true
Scalaz(5)- typeclass:my typeclass scalaz style-demo的更多相关文章
- Scalaz(43)- 总结 :FP就是实用的编程模式
完成了对Free Monad这部分内容的学习了解后,心头豁然开朗,存在心里对FP的疑虑也一扫而光.之前也抱着跟大多数人一样的主观概念,认为FP只适合学术性探讨.缺乏实际应用.运行效率低,很难发展成现实 ...
- Scalaz(22)- 泛函编程思维: Coerce Monadic Thinking
马上进入新的一年2016了,来点轻松点的内容吧.前面写过一篇关于用Reader实现依赖注入管理的博文(Scalaz(16)- Monad:依赖注入-Dependency Injection By Re ...
- Scalaz(25)- Monad: Monad Transformer-叠加Monad效果
中间插播了几篇scalaz数据类型,现在又要回到Monad专题.因为FP的特征就是Monad式编程(Monadic programming),所以必须充分理解认识Monad.熟练掌握Monad运用.曾 ...
- Scalaz(53)- scalaz-stream: 程序运算器-application scenario
从上面多篇的讨论中我们了解到scalaz-stream代表一串连续无穷的数据或者程序.对这个数据流的处理过程就是一个状态机器(state machine)的状态转变过程.这种模式与我们通常遇到的程序流 ...
- MySQL数据分析-(15)表补充:存储引擎
大家好,我是jacky,很高兴继续跟大家分享<MySQL数据分析实战>,今天跟大家分享的主题是表补充之存储引擎: 我们之前学了跟表结构相关的一些操作,那我们看一下创建表的SQL模型: 在我 ...
- STL笔记(6)标准库:标准库中的排序算法
STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...
- java中文乱码解决之道(三)-----编码详情:伟大的创想---Unicode编码
随着计算机的发展.普及,世界各国为了适应本国的语言和字符都会自己设计一套自己的编码风格,正是由于这种乱,导致存在很多种编码方式,以至于同一个二进制数字可能会被解释成不同的符号.为了解决这种不兼容的问题 ...
- Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition
Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...
- Android Animation学习(四) ApiDemos解析:多属性动画
Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...
- Android Animation学习(三) ApiDemos解析:XML动画文件的使用
Android Animation学习(三) ApiDemos解析:XML动画文件的使用 可以用XML文件来定义Animation. 文件必须有一个唯一的根节点: <set>, <o ...
随机推荐
- C#学习系列-this的使用
如有错误,欢迎指正. 1.代表当前类,在当前类中可使用this访问当前类成员变量和方法(需要注意的是 静态方法中不能使用this),也可用于参数传递,传递当前对象的引用. 下面贴代码: class P ...
- 类的继承和多态性-编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 getLegs(),设置动物名称的方法 setKind(),获得动物名称的方法 getKind(),获得动物数量的方法 getCount()。定义Fish类,是Animal类的子类,
编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 ...
- CSS实现水平垂直同时居中的5种思路
× 目录 [1]水平对齐+行高 [2]水平+垂直对齐 [3]margin+垂直对齐[4]absolute[5]flex 前面的话 水平居中和垂直居中已经单独介绍过,本文将介绍水平垂直同时居中的5种思路 ...
- Floyd算法(二)之 C++详解
本章是弗洛伊德算法的C++实现. 目录 1. 弗洛伊德算法介绍 2. 弗洛伊德算法图解 3. 弗洛伊德算法的代码说明 4. 弗洛伊德算法的源码 转载请注明出处:http://www.cnblogs.c ...
- 打开都是“Smart Adobe CC Blocker v1.0”已损坏,打不开。 您应该将它移到废纸篓。
安全设置里允许任意来源打开就可以了 “系统偏好设置”->“安全性与隐私”->“允许从以下位置下载的应用程序”->任何来源.
- Office英语学习好帮手
Office提供了强大实用的英语学习助手,它可以自动翻译中英文,还可以显示详尽的解释帮助信息,当然标准的发音也是必不可少的.如何启动屏幕取词翻译功能呢?如何让office自动取词并翻译呢?如何收听单词 ...
- Spring学习总结(四)——表达式语言 Spring Expression Language
SpEL简介与功能特性 Spring表达式语言(简称SpEL)是一个支持查询并在运行时操纵一个对象图的功能强大的表达式语言.SpEL语言的语法类似于统一EL,但提供了更多的功能,最主要的是显式方法调用 ...
- Android基于mAppWidget实现手绘地图(五)--如何创建地图资源
地图资源可以通过Slicing Tool工具生成,教程如下: 1.打开Eclipse标准版4.3.2,以Java项目形式导入”slicingtool“项目,运行.(必须是eclipse4.3.2及以上 ...
- Robot Framework自动化测试(七)--- jybot模式
虽然,很久不用关于Robot Framework框架了,但我这里应该是除了@齐涛-道长之外分享Robot Framework 相关资料比较多的地方了.所以,常常被问到一些关于该框架的问题. 虽然,我一 ...
- 12款界面精美的 HTML5 & CSS3 网站模板
这里分享的12款完全采用响应式设计的 HTML5 & CSS3 网站设计模板.每一个细节都精心设计,以创建一个美妙的用户体验.这些响应主题和模板最适合用于电子商务,商业门户网站,个人作品集以及 ...