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


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._
2 
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



10.isNonZero                                      //> res7: Boolean = true
0.isNonZero                                       //> res8: 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



10.isNonZero                                      //> res7: Boolean = true
0.isNonZero                                       //> res8: Boolean = false
2.isNonZero                                       //> res9: Boolean = true


相关文章
|
2天前
|
存储 JavaScript 前端开发
JavaScript基础
本节讲解JavaScript基础核心知识:涵盖值类型与引用类型区别、typeof检测类型及局限性、===与==差异及应用场景、内置函数与对象、原型链五规则、属性查找机制、instanceof原理,以及this指向和箭头函数中this的绑定时机。重点突出类型判断、原型继承与this机制,助力深入理解JS面向对象机制。(238字)
|
1天前
|
云安全 人工智能 安全
阿里云2026云上安全健康体检正式开启
新年启程,来为云上环境做一次“深度体检”
1470 6
|
3天前
|
安全 数据可视化 网络安全
安全无小事|阿里云先知众测,为企业筑牢防线
专为企业打造的漏洞信息收集平台
1304 2
|
3天前
|
缓存 算法 关系型数据库
深入浅出分布式 ID 生成方案:从原理到业界主流实现
本文深入探讨分布式ID的生成原理与主流解决方案,解析百度UidGenerator、滴滴TinyID及美团Leaf的核心设计,涵盖Snowflake算法、号段模式与双Buffer优化,助你掌握高并发下全局唯一ID的实现精髓。
319 160
|
3天前
|
人工智能 自然语言处理 API
n8n:流程自动化、智能化利器
流程自动化助你在重复的业务流程中节省时间,可通过自然语言直接创建工作流啦。
365 4
n8n:流程自动化、智能化利器
|
11天前
|
机器学习/深度学习 安全 API
MAI-UI 开源:通用 GUI 智能体基座登顶 SOTA!
MAI-UI是通义实验室推出的全尺寸GUI智能体基座模型,原生集成用户交互、MCP工具调用与端云协同能力。支持跨App操作、模糊语义理解与主动提问澄清,通过大规模在线强化学习实现复杂任务自动化,在出行、办公等高频场景中表现卓越,已登顶ScreenSpot-Pro、MobileWorld等多项SOTA评测。
1476 7
|
5天前
|
人工智能 API 开发工具
Skills比MCP更重要?更省钱的多!Python大佬这观点老金测了一周终于懂了
加我进AI学习群,公众号右下角“联系方式”。文末有老金开源知识库·全免费。本文详解Claude Skills为何比MCP更轻量高效:极简配置、按需加载、省90% token,适合多数场景。MCP仍适用于复杂集成,但日常任务首选Skills。推荐先用SKILL.md解决,再考虑协议。附实测对比与配置建议,助你提升效率,节省精力。关注老金,一起玩转AI工具。
|
1天前
|
Linux 数据库
Linux 环境 Polardb-X 数据库 单机版 rpm 包 安装教程
本文介绍在CentOS 7.9环境下安装PolarDB-X单机版数据库的完整流程,涵盖系统环境准备、本地Yum源配置、RPM包安装、用户与目录初始化、依赖库解决、数据库启动及客户端连接等步骤,助您快速部署运行PolarDB-X。
228 1
Linux 环境 Polardb-X 数据库 单机版 rpm 包 安装教程
|
12天前
|
人工智能 Rust 运维
这个神器让你白嫖ClaudeOpus 4.5,Gemini 3!还能接Claude Code等任意平台
加我进AI讨论学习群,公众号右下角“联系方式”文末有老金的 开源知识库地址·全免费
1342 17
|
3天前
|
自然语言处理 监控 测试技术
互联网大厂“黑话”完全破译指南
互联网大厂黑话太多听不懂?本文整理了一份“保姆级”职场黑话词典,涵盖PRD、A/B测试、WLB、埋点、灰度发布等高频术语,用大白话+生活化类比,帮你快速听懂同事在聊什么。非技术岗也能轻松理解,建议收藏防踩坑。
274 161

热门文章

最新文章