《类型编程晋级——shapeless类库使用指南》前言及第一章翻译
从年初开始进行此项工作,我和合作伙伴包亮付出了大量而艰辛的劳动。翻译中我们本着能够让所有人看明白、看懂的目的,反复修改高达五次。现基本翻译完毕,有出版意向,如果有意向欢迎联系,不甚感激!现在此文中展示其中的前言和第一章,欢迎各位博友对此翻译提出意见建议以及指导如何出版,在此谢过!
- 原名:The Type Astronaut's Guide to Shapeless
- 中文:类型编程晋级——shapeless类库使用指南
- 作者:Dave Gurnell(戴夫·格内尔)
- 翻译:魏守峰、包亮
前言
时间回到2011年初,我做了一些泛型编程(generic programming)的实验,最后这些实验形成了shapeless,我绝不会想到五年后它居然会成为一个被如此广泛使用的类库。非常感谢那些信任我并将shapeless用到项目中的人,这种信任对任何开源项目来说都是巨大的动力。同样感谢多年来对项目做出巨大贡献的人,截止写此书时共有81人,没有它们的帮助shapeless不可能这么有趣和有用。
尽管有这些积极因素,shapeless也经历了所有开源项目的通病:缺乏完善的、准确的、易懂的文档。尽管我知晓这一点,但还是没能抽出时间在这方面做些事情,责任全在我。Travis Brown在Stack Overflow的英勇的表现以及很多人的讨论和实践,从一定程度上弥补了这一缺陷(此处我要特别指出Sam Halliday的“Shapeless for Mortals”)。
但是Dave Gurnell改变了这一切:他为我们写了这本精彩的书,此书介绍了shapeless的最重要的应用:通过泛型编程实现类型类(type class)派生。为了写此书他搜集了大量的代码和文档,征求了我的意见,并将杂乱无章变的清晰、简明、实用。幸运的是他很好的实现了我的主张——shapeless是一个非常简单的类库,它体现了一系列简单的原则。 感谢Dave,你为我们做了一件伟大的事情。
Miles Sabin
shapeless作者
概要
此书是关于如何使用shapeless的指导,shapeless是基于Scala语言的泛型编程库。由于shapeless包含的内容过多,所以此书只是专注于一些非常有意思的使用案例并用它们描绘出一个可用的工具和编程模式的画面。
在本章开始处,先来介绍一下什么是泛型编程以及是什么原因使得shapeless让Scala开发者如此兴奋。
1.1 什么是泛型编程?
具体的类型是有帮助的,它向我们展示不同的代码片段如何能够组合到一起、帮助我们消除bug以及当我们编写代码的时候引导我们找到解决方案。
然而有时类型又太具体,有些情形下我们想探索不同类型之间的相似性来去除重复编码工作。例如,考虑以下两个类型:
case class Employee(name: String, number: Int, manager: Boolean)
case class IceCream(name: String, numCherries: Int, inCone: Boolean)
这两个模式类代表不同的数据种类,但是它们又非常相似,每种都包含三个类型相同的字段。假设我们要实现一个对它们都通用的操作,例如将它们的实例序列化到CSV文件中,尽管这两类数据相似,但是我们不得不写两个不同的方法来处理。分别如下:
def employeeCsv(e: Employee): List[String] =
List(e.name, e.number.toString, e.manager.toString)
def iceCreamCsv(c: IceCream): List[String] =
List(c.name, c.numCherries.toString, c.inCone.toString)
泛型编程能够克服像上面这样由于不同数据类型带来的重复操作。shapeless很容易实现将具体的类型泛型化,这样就可以使用同一段代码来操作不同的类型。
比如,我们能用如下代码将employees和ice creams实例转换成同一类型。不用担心不理解以下代码,本书会在接下来的章节中详细介绍这些它们。
import shapeless._
val genericEmployee = Generic[Employee].to(Employee("Dave", 123, false))
// genericEmployee: shapeless.::[String,shapeless.::[Int,shapeless.::[
Boolean,shapeless.HNil]]] = Dave :: 123 :: false :: HNil
val genericIceCream = Generic[IceCream].to(IceCream("Sundae", 1, false))
// genericIceCream: shapeless.::[String,shapeless.::[Int,shapeless.::[
Boolean,shapeless.HNil]]] = Sundae :: 1 :: false :: HNil
现在两个值变成了相同类型,都是异构的列表(简称HList),它包含一个字符串(String)、一个整型(Int)和一个布尔(Boolean)对象。接下来我们将研究HList类型和它在shapeless中所扮演的重要角色。目前为止关键问题在于我们已经解决了用同一个函数来序列化上面两种经过类型变换后的值。代码如下:
def genericCsv(gen: String :: Int :: Boolean :: HNil): List[String] =
List(gen(0), gen(1).toString, gen(2).toString)
genericCsv(genericEmployee)
// res2: List[String] = List(Dave, 123, false)
genericCsv(genericIceCream)
// res3: List[String] = List(Sundae, 1, false)
这个简单的例子展示了泛型编程的精髓。重新探究这些问题之后,我们用泛型代码块解决了问题并写出了适用于多种类型的精简代码。使用shapeless进行泛型编程可以消除大量的冗余代码,使Scala应用程序更容易读、写和维护。
听上去是不是很有诱惑?想想这些,让我们一起入坑吧!
1.2 关于此书
该书共分为两部分。
第一部分介绍类型类(type class)派生,这允许我们仅用一些泛型规则来为任何代数数据类型(algebraic data type,简称ADT)创建类型类实例。第一部分包含四章。
第二章介绍泛型表示(generic representation),以及shapeless中名为Generic的类型类,Generic能够为任何一个模式类(case class)或密封特质(sealed trait)创建一个泛型解码器,将其转化为泛型。
第三章用Generic派生自定义类型类实例,并创建一个类型类的例子用于将Scala中的数据编码为CSV格式,但是此技术可以扩展到许多情形。此外还介绍了shapeless中的Lazy类型,可以处理像列表(list)以及树(tree)等类型的递归数据。
第四章介绍前几章涉及的理论和编程模式,特别是针对依赖类型、类型依赖函数以及类型级别编程,这些能使我们进入更高级的shapeless应用。
第五章介绍LabelledGeneric,这是Generic的一个变体,它将字段名称和类型名称转换为其泛型表示的一部分。还介绍了一些理论知识:字面类型( literal)、单例类型(singleton)、幽灵类型(phantom)和类型标签(type tagging)。我们会创建一个在输出中保持字段和类型名称不变的JSON编码器,以此来演示LabelledGeneric。
第二部分介绍在shapeless.ops包中提供的“ops类型类”,它来源于一个处理泛型表示工具的扩展库。在接下来的三章中仅为大家介绍入门理论,而不是介绍每一个操作(op)的细节。
第六章介绍ops类型类的通用设计方式并提供一个例子,实现将几个简单操作串联到一起组成一个强大的“模式类迁移”工具。
第七章介绍多态函数(Poly)并展示在ops类型类中如何使用多态函数对“泛型表示”进行操作,这些操作包含map、flat Map以及fold。
第八章介绍shapeless中用于在类型级别表示原始数字的Nat类型。介绍几个相关的ops类型类并用Nat建立我们自己的ScalaCheck(一个Scala测试框架)中的Arbitrary(随机数生成)类。
1.3 源码和例子
此书是开源的,你可以在Github中找到其markdown格式。本书会持续更新,所以请检查上述Github仓库以获取最新版本。
书中的大多数例子已经实现,你可以在此仓库中找到它们。细节请参考README文件。
我们推荐shapeless2.3.2版以及Typelevel Scala2.11.8+版或者Lightbend Scala2.11.9+/2.12.1+版。
1.4 致谢
感谢Miles Sabin、Richard Dallaway、Noel Welsh、Travis Brown和我们的Github仓库中的贡献者,他们为这本指导提供了不可估量的贡献。
特别感谢Sam Halliday,他的优秀的Shapeless for Mortals库为我们提供了最初的灵感和骨架。
最后,感谢Rob Norris和他的Tut库的跟随者,他们对我们的例子做了精心的验证,确保其编译无误。
《类型编程晋级——shapeless类库使用指南》前言及第一章翻译的更多相关文章
- 《深入理解Spark:核心思想与源码分析》(前言及第1章)
自己牺牲了7个月的周末和下班空闲时间,通过研究Spark源码和原理,总结整理的<深入理解Spark:核心思想与源码分析>一书现在已经正式出版上市,目前亚马逊.京东.当当.天猫等网站均有销售 ...
- C++的XML编程经验――LIBXML2库使用指南[转]
C++的XML编程经验――LIBXML2库使用指南 写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML ...
- C++的XML编程经验――LIBXML2库使用指南
C++的XML编程经验――LIBXML2库使用指南 写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML ...
- 如何理解 TS 类型编程中的 extends 和 infer
extends extends 在TS类型编程中用法(T extends U),表示 T 中的某些在 U 里面,比较难描述,用法如下: T extends U ? X : Y 分为两种情况理解更直观一 ...
- 《 .NET并发编程实战》一书中的节流为什么不翻译成限流
有读者问,为什么< .NET并发编程实战>一书中的节流为什么不翻译成限流? 这个问题问得十分好!毕竟“限流”这个词名气很大,耳熟能详,知名度比“节流”大多了. 首先,节流的原词Thrott ...
- 《NodeJs开发指南》第五章微博开发实例的中文乱码问题
在<NodeJs开发指南>第五章,按照书中的要求写好微博实例后,运行代码,发现中文显示出现乱码,原因是:views文件夹下的ejs文件的编码格式不是utf-8. 解决方法:以记事本方式打开 ...
- WCF分布式开发步步为赢(9):WCF服务实例激活类型编程与开发
.Net Remoting的激活方式也有三种:SingleTon模式.SingleCall模式.客户端激活方式,WCF服务实例激活类型包括三种方式:单调服务(Call Service),会话服务(Se ...
- .NET本质论 用类型编程
运行时的类型 类型本身并不是万能的.类型真正有意思的地方在于,程序员使用类型的实例,并让它们相互作用.类型的实例(instance)既可以是对象,也可以是值,这取决于类型如何定义的.基本数据类型(pr ...
- 进阶Java编程(5)基础类库
Java基础类库 1,StringBuffer类 String类是在所有项目开发之中一定会使用到的一个功能类,并且这个类拥有如下的特点: ①每一个字符串的常量都属于一个String类的匿名对象,并且不 ...
随机推荐
- 安装MYSql Windows7下MySQL5.5.20免安装版的配置
MySQL Windows安装包说明: 1.mysql-5.5.20-win32.msi:Windows 安装包,图形化的下一步下一步的安装. 2.mysql-5.5.20.zip,这个是window ...
- Bootstrap3网上api文档地址
http://v3.bootcss.com/css/#forms http://www.ziqiangxuetang.com/bootstrap/bootstrap-forms.html 另附加fa字 ...
- jquery的动画函数animate()讲解一
jquery animate 动画效果使用说明 animate( params, [duration], [easing], [callback] ) 用于创建自定义动画的函数. 这个函数的关键在于指 ...
- BNU Online Judge-34976-数细菌
题目链接 http://www.bnuoj.com/bnuoj/problem_show.php?pid=34976 题目分析通过a b可以设x,y x+y=a x+3*y=b 解出x,y, ...
- HTML5 简介、HTML5 浏览器支持
HTML5是HTML最新的修订版本,2014年10月由万维网联盟(W3C)完成标准制定. HTML5的设计目的是为了在移动设备上支持多媒体. HTML5 简单易学. 什么是 HTML5? HTML5 ...
- Java学习之旅基础知识篇:数组及引用类型内存分配
在上一篇中,我们已经了解了数组,它是一种引用类型,本篇将详细介绍数组的内存分配等知识点.数组用来存储同一种数据类型的数据,一旦初始化完成,即所占的空间就已固定下来,即使某个元素被清空,但其所在空间仍然 ...
- JavaScript中DOM的层次节点(一)
DOM是针对HTML和XML文档的一个API,描绘了一个层次化的节点树,允许开发人员添加.修改.删除节点的一部分. DOM将HTML和XML文档描绘成一个有多个节点构成的结构,节点分为12种不同的节点 ...
- Docker环境中部署OwnCloud 9.0
整体思路: 1.官方获取mysql.php+apache镜像: 2.基于php+apache,创建OwnCloud镜像: 3.启动mysql镜像: 4.启动OwnCloud镜像,链接mysql镜像,访 ...
- ArcGIS 网络分析[1] 介绍与博文目录【更新中】
网络分析是个热点,理论上是属于计算机图形学和数据结构的,GIS以此为基础做出应用. 以下列举本人在学习中遇到的网络分析问题与经验总结. 平台:Windows 10操作系统,ArcGIS for Des ...
- [Bullet3]创建世界(场景)及常见函数
创建世界(场景)及常见函数 官方文档:http://bulletphysics.org 开源代码:https://github.com/bulletphysics/bullet3/releases A ...