基本信息
书 名
C#函数式编程 编写更优质的C#代码
外文书名
出版社
清华大学出版社
作 者
(美)恩里科·博南诺
定 价
98.00元
出版时间
2019.01
I S B N
9787302510550
套装书
否
重 量
KG
装 帧
平装
版 次
1
字 数
页 数
开 本
16开
内容简介
函数式编程将改变你思考代码的方式!利用FP技术,C#开发人员可极大地提升状态管理、并发处理和事件处理能力,并更好地长期维护代码。C#提供了灵活性,使你能充分利用函数式技术的优势。《C#函数式编程 编写更优质的C#代码》从全新视角赋予你强大力量。
《C#函数式编程 编写更优质的C#代码》引导你在C#语言中使用函数式思想来解决现实问题;首先介绍函数式编程的原理,分析如何借助C#语言特性实现函数式编程,然后在多个紧贴实用的示例的引导下,讲述函数组合、数据流编程、不可变数据结构以及使用LINQ构建单子组合等主题。
目 录
●第Ⅰ部分核心概念 章介绍函数式编程3 1.1什么是函数式编程4 1.1.1函数作为类值4 1.1.2避免状态突变4 1.1.3编写具有强力保证的程序5 1.2C#的函数式语言8 1.2.1LINQ的函数式性质9 1.2.2C#6和C#7中的函数式特性10 1.2.3未来的C#将更趋函数化13 1.3函数思维13 1.3.1映射函数13 1.3.2在C#中表示函数14 1.4高阶函数18 1.4.1依赖于其他函数的函数18 1.4.2适配器函数20 1.4.3创建其他函数的函数20 1.5使用HOF避免重复21 1.5.1将安装和拆卸封装到HOF中23 1.5.2将using语句转换为HOF24 1.5.3HOF的权衡25 1.6函数式编程的好处27 练习27 小结28 第2章为什么函数纯洁性很重要29 2.1什么是函数的纯洁性29 2.1.1纯洁性和副作用30 2.1.2管理副作用的策略31 2.2纯洁性和并发性33 2.2.1纯函数可良好地并行化34 2.2.2并行化不纯函数35 2.2.3避免状态的突变36 2.3纯洁性和可测性38 2.3.1实践:一个验证场景39 2.3.2在测试中引入不纯函数40 2.3.3为什么很难测试不纯函数42 2.3.4参数化单元测试43 2.3.5避免标头接口44 2.4纯洁性和计算的发展47 练习47 小结48 第3章设计函数签名和类型49 3.1函数签名设计49 3.1.1箭头符号50 3.1.2签名的信息量有多大51 3.2使用数据对象捕获数据52 3.2.1原始类型通常不够具体53 3.2.2使用自定义类型约束输入53 3.2.3编写“诚实的”函数55 3.2.4使用元组和对象来组合值56 3.3使用Unit为数据缺失建模58 3.3.1为什么void不理想58 3.3.2使用Unit弥合Action和Func之间的差异59 3.4使用Option为数据可能缺失建模61 3.4.1你每天都在使用糟糕的API61 3.4.2Option类型的介绍62 3.4.3实现Option65 3.4.4通过使用Option而不是null来获得健壮性68 3.4.5Option作为偏函数的自然结果类型69 练习73 小结74 第4章函数式编程中的模式77 4.1将函数应用于结构的内部值77 4.1.1将函数映射到序列上77 4.1.2将函数映射到Option79 4.1.3Option是如何提高抽象层级的81 4.1.4函子82 4.2使用ForEach执行副作用83 4.3使用Bind来链接函数85 4.3.1将返回Option的函数结合起来85 4.3.2使用Bind平铺嵌套列表87 4.3.3实际上,这被称为单子88 4.3.4Return函数88 4.3.5函子和单子之间的关系89 4.4使用Where过滤值90 4.5使用Bind结合Option和IEnumerable91 4.6在不同抽象层级上编码92 4.6.1常规值与不错值93 4.6.2跨越抽象层级94 4.6.3重新审视Map与Bind95 4.6.4在正确的抽象层级上 工作96 练习96 小结97 第5章使用函数组合设计程序99 5.1函数组合99 5.1.1复习函数组合100 5.1.2方法链101 5.1.3不错值界域中的组合101 5.2从数据流的角度进行思考102 5.2.1使用LINQ的可组合 API102 5.2.2编写可组合性更好的函数103 5.3工作流编程105 5.3.1关于验证的一个简单 工作流106 5.3.2以数据流的思想进行重构107 5.3.3组合带来了更大的灵活性108 5.4介绍函数式领域建模109 5.5端到端的服务器端工作流110 5.5.1表达式与语句112 5.5.2声明式与命令式112 5.5.3函数式分层113 练习115 小结115 第Ⅱ部分函数式风格 第6章函数式错误处理119 6.1表示输出的更安全方式120 6.1.1使用Either捕获错误细节120 6.1.2处理Either的核心函数123 6.1.3比较Option和Either124 6.2链接操作可能失败125 6.3验证:Either的一个完美用例127 6.3.1为错误选择合适的表示法128 6.3.2定义一个基于Either的API129 6.3.3添加验证逻辑130 6.4将输出提供给客户端应用程序131 6.4.1公开一个类似Option的接口132 6.4.2公开一个类似Either的接口134 6.4.3返回一个DTO结果134 6.5Either的变体136 6.5.1在不同的错误表示之间进行改变136 6.5.2Either的特定版本137 6.5.3重构Validation和Exceptional138 6.5.4保留异常141 练习142 小结142 第7章用函数构造一个应用程序145 7.1偏函数应用:逐个提供参数146 7.1.1手动启用偏函数应用147 7.1.2归纳偏函数应用148 7.1.3参数的顺序问题150 7.2克服方法解析的怪癖150 7.3柯里化函数:优化偏函数应用152 7.4创建一个友好的偏函数应用API155 7.4.1可文档化的类型156 7.4.2具化数据访问函数157 7.5应用程序的模块化及 组合159 7.5.1OOP中的模块化160 7.5.2FP中的模块化162 7.5.3比较两种方法164 7.5.4组合应用程序165 7.6将列表压缩为单个值166 7.6.1LINQ的Aggregate方法166 7.6.2聚合验证结果168 7.6.3收获验证错误169 练习170 小结171 第8章有效地处理多参函数173 8.1不错界域中的函数应用程序174 8.1.1理解应用式176 8.1.2提升函数177 8.1.3介绍基于属性的测试179 8.2函子、应用式、单子181 8.3单子定律182 8.3.1右恒等元183 8.3.2左恒等元183 8.3.3结合律184 8.3.4对多参函数使用Bind185 8.4通过对任何单子使用LINQ来提高可读性186 8.4.1对任意函子使用LINQ186 8.4.2对任意单子使用LINQ188 8.4.3let、where及其他LINQ子句191 8.5何时使用Bind或Apply192 8.5.1具有智能构造函数的验证192 8.5.2使用应用式流来收集错误194 8.5.3使用单子流来快速失败195 练习196 小结196 第9章关于数据的函数式思考199 9.1状态突变的陷阱200 9.2理解状态、标识及变化202 9.2.1有些事物永远不会变化203 9.2.2表示非突变的变化205 9.3强制不可变性207 9.3.1永远不可变209 9.3.2无样板代码的拷贝方法的可行性210 9.3.3利用F#处理数据类型212 9.3.4比较不变性的策略:一场丑陋的比赛213 9.4函数式数据结构简介214 9.4.1经典的函数式链表215 9.4.2二叉树219 练习223 小结224 0章事件溯源:持久化的函数式方法225 10.1关于数据存储的函数式思考226 10.1.1为什么数据存储只能追加226 10.1.2放松,并忘却存储状态227 10.2事件溯源的基础知识228 10.2.1表示事件228 10.2.2持久化事件229 10.2.3表示状态230 10.2.4一个模式匹配的插曲231 10.2.5表示状态转换234 10.2.6从过去的事件中重建当前状态235 10.3事件溯源系统的架构236 10.3.1处理命令237 10.3.2处理事件240 10.3.3添加验证241 10.3.4根据事件创建数据的视图243 10.4比较不可变存储的不同方法246 10.4.1Datomic与 EventStore247 10.4.2你的领域是否受事件驱动?247 小结248 第Ⅲ部分不错技术 1章惰性计算、延续以及单子组合之美251 11.1惰性的优点251 11.1.1用于处理Option的惰性API252 11.1.2组合惰性计算254 11.2使用Try进行异常处理256 11.2.1表示可能失败的计算257 11.2.2从JSON对象中安全地提取信息257 11.2.3组合可能失败的计算259 11.2.4单子组合:是什么意思呢?260 11.3为数据库访问创建中间件管道261 11.3.1组合执行安装/拆卸的函数261 11.3.2逃离厄运金字塔的秘方263 11.3.3捕获中间件函数的本质263 11.3.4实现中间件的查询模式265 11.3.5添加计时操作的中间件268 11.3.6添加管理数据库事务的中间件269 小结271 2章有状态的程序和计算273 12.1管理状态的程序274 12.1.1维护所检索资源的缓存275 12.1.2重构可测试性和错误处理277 12.1.3有状态的计算278 12.2一种用于生成随机数据的语言279 12.2.1生成随机整数280 12.2.2生成其他基元281 12.2.3生成复杂的结构282 12.3有状态计算的通用模式284 小结287 3章使用异步计算289 13.1异步计算290 13.1.1对异步的需要290 13.1.2用Task表示异步操作291 13.1.3Task作为一个将来值的容器292 13.1.4处理失败294 13.1.5一个用于货币转换的HTTPAPI296 13.1.6如果失败,请再试几次297 13.1.7并行运行异步操作297 13.2遍历:处理不错值列表299 13.2.1使用单子的Traverse来验证值列表301 13.2.2使用应用式Traverse来收集验证错误302 13.2.3将多个验证器应用于单个值304 13.2.4将Traverse与Task一起使用以等待多个结果305 13.2.5为单值结构定义Traverse306 13.3结合异步和验证(或其他任何两个单子效果)308 13.3.1堆叠单子的问题308 13.3.2减少效果的数量310 13.3.3具有一个单子堆叠的LINQ表达式311 小结312 4章数据流和ReactiveExtensions315 14.1用IObservable表示数据流316 14.1.1时间上的一个序列的值316 14.1.2订阅IObservable317 14.2创建IObservable318 14.2.1创建一个定时器319 14.2.2使用Subject来告知IObservable应何时发出信号320 14.2.3从基于回调的订阅中创建IObservable320 14.2.4由更简单的结构创建IObservable321 14.3转换和结合数据流323 14.3.1流的转换323 14.3.2结合和划分流325 14.3.3使用IObservable进行错误处理327 14.3.4融会贯通329 14.4实现贯穿多个事件的逻辑330 14.4.1检测按键顺序330 14.4.2对事件源作出反应333 14.4.3通知账户何时透支335 14.5应该何时使用IObservable?337 小结338 5章并发消息传递339 15.1对共享可变状态的需要339 15.2理解并发消息传递341 15.2.1在C#中实现代理343 15.2.2开始使用代理344 15.2.3使用代理处理并发请求346 15.2.4代理与角色349 15.3“函数式API”与“基于代理的实现”350 15.3.1代理作为实现细节351 15.3.2将代理隐藏于常规API的背后352 15.4LOB应用程序中的并发消息传递353 15.4.1使用代理来同步对账户数据的访问354 15.4.2保管账户的注册表356 15.4.3代理不是一个对象357 15.4.4融会贯通359 小结361 结束语:接下来呢?363