[Compose] 21. Apply Natural Transformations in everyday work
We see three varied examples of where natural transformations come in handy.
Let's mark the law here for Natural Transformations:
nt(F).map(f) === nf(F.map(f))
Then let's see why we might need to apply Natural Transformations:
1. Natural Transformations can improve the code proformance
For example, we have an array of numbers, we want to get larger number, apply a doulbe function, then only get first element out of the array.
const first = xs => fromNullable(xs[]);
const largeNumbers = xs => xs.filter(x => x > );
const doulbe = x => x * ; // We first run though the whole array to doulbe the number
// Then apply first to either transform -> Proformance cost
// Since nt(F).map(f) === nt(F.map(f))
const transform1 = xs => first(largeNumbers(xs).map(doulbe));
const app = xs => transform1(xs);
console.log(app([,,,])); // Either { value: 800 }
Imporved one should be get only first of larger number, then apply transform:
const first = xs => fromNullable(xs[]);
const largeNumbers = xs => xs.filter(x => x > );
const doulbe = x => x * ; // Now we get first of array and transform to either, then apply our doulbe function
const transform2 = xs => first(largeNumbers(xs)).map(doulbe);
const app = xs => transform2(xs);
console.log(app([,,,])); // Either { value: 800 }
2. Solve different nested Functors:
const fake = id =>
({id, name: 'user1', best_friend_id: id + });
// Db :: find :: id -> Task(Either)
const Db = ({
find: id => new Task((rej, res) => {
res(id > ? Right(fake(id)): Left('not found'))
})
});
For example, the code above, we have a Db.find function, which return Task(Either(User)). It would be much easier for us to work with the same Functor type, instead of multi functors. we can think about change
// Either -> Task
const eitherToTask = e =>
e.fold(Task.rejected, Task.of);
With this tool, let's see how it solve us problem:
Db.find() // Task(Right(User))
Now we chain 'eitherToTask':
Db.find() // Task(Right(User))
.chain(eitherToTask) // // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
So after run though 'eitherToTask' we change 'Right to Task' we got 'Task(Task(User)), then the outmost 'chain' will remove 'Task(User)'
Now if we want to find User's best friend id:
Db.find() // Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
.chain(user => Db.find(user.best_friend_id)) // Task(User) --Db.find--> Task(Task(Right(User))) --chain--> Task(Right(User))
We know that 'Db.find(user.best_friend_id)' returns 'Task(Right(User))', inner most function call return 'Task(Task(Right(User)))', after outter most 'chain', we got 'Task(Right(User))'.
Now we can apply the trick again:
Db.find() // Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
.chain(user => Db.find(user.best_friend_id)) // Task(User) --Db.find--> Task(Task(Right(User))) --chain--> Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
We only got 'Task(User)' in the end, ready to be forked!
Db.find() // Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
.chain(user => Db.find(user.best_friend_id)) // Task(User) --Db.find--> Task(Task(Right(User))) --chain--> Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
.fork(console.error, console.log); // { id: 5, name: 'user1', best_friend_id: 6 }
--
const Either = require('data.either');
const Task = require('data.task');
const {List, Map} = require('immutable-ext');
const {Right, Left, fromNullable} = Either; const log = console.log; // F a -> G a
// nt(F).map(f) === nt(F.map(f)) //////Exp1/////
const res = List(['Hello', 'wolrd']).chain(x => x.split(''));
console.log(res.toJS()); // [ 'H', 'e', 'l', 'l', 'o', 'w', 'o', 'l', 'r', 'd' ] //////Exp2/////
const first = xs => fromNullable(xs[]);
const largeNumbers = xs => xs.filter(x => x > );
const doulbe = x => x * ; // We first run though the whole array to doulbe the number
// Then apply first to either transform -> Proformance cost
// Since nt(F).map(f) === nt(F.map(f))
const transform1 = xs => first(largeNumbers(xs).map(doulbe));
// Now we get first of array and transform to either, then apply our doulbe function
const transform2 = xs => first(largeNumbers(xs)).map(doulbe);
const app = xs => transform2(xs);
console.log(app([,,,])); // Either { value: 800 } //////Exp3/////const fake = id =>
({id, name: 'user1', best_friend_id: id + });
// Db :: find :: id -> Task(Either)
const Db = ({
find: id => new Task((rej, res) => {
res(id > ? Right(fake(id)): Left('not found'))
})
}); const eitherToTask = e =>
e.fold(Task.rejected, Task.of); Db.find() // Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
.chain(user => Db.find(user.best_friend_id)) // Task(User) --Db.find--> Task(Task(Right(User))) --chain--> Task(Right(User))
.chain(eitherToTask) // Task(Right(User)) --EtT--> Task(Task(User)) --chain--> Task(User)
.fork(console.error, console.log); // { id: 5, name: 'user1', best_friend_id: 6 }
[Compose] 21. Apply Natural Transformations in everyday work的更多相关文章
- [Compose] 20. Principled type conversions with Natural Transformations
We learn what a natural transformation is and see the laws it must obey. We will see how a natural t ...
- [Compose] 16. Apply multiple functors as arguments to a function (Applicatives)
We find a couple of DOM nodes that may or may not exist and run a calculation on the page height usi ...
- JDK8新特性 -- Function接口: apply,andThen,compose
1 Function<T, R>中的T, R表示接口输入.输出的数据类型. R apply(T t) apply: .例子:func是定义好的Function接口类型的变量,他的输入.输出 ...
- [转]Neural Networks, Manifolds, and Topology
colah's blog Blog About Contact Neural Networks, Manifolds, and Topology Posted on April 6, 2014 top ...
- 壁虎书2 End-to-End Machine Learning Project
the main steps: 1. look at the big picture 2. get the data 3. discover and visualize the data to gai ...
- 2020你还不会Java8新特性?
Java8(1)新特性介绍及Lambda表达式 前言: 跟大娃一块看,把原来的电脑拿出来放中间看视频用 --- 以后会有的课程 难度 深入Java 8 难度1 并发与netty 难度3 JVM 难度4 ...
- [转载] 首席工程师揭秘:LinkedIn大数据后台是如何运作的?(一)
本文作者:Jay Kreps,linkedin公司首席工程师:文章来自于他在linkedin上的分享:原文标题:The Log: What every software engineer should ...
- [Javascript] Functor law
Functor laws: 1. Identity: map(id) == id 2. Composition: compose(map(f), map(g)) == map(compose(f,g) ...
- Category Theory: 01 One Structured Family of Structures
Category Theory: 01 One Structured Family of Structures 这次看来要放弃了.看了大概三分之一.似乎不能够让注意力集中了.先更新吧. 群的定义 \( ...
随机推荐
- Windows下Qt5搭建Android开发环境笔记
Windows很大的特点是配置使用几乎都可以图形化进行,和Linux比起来在很多时候配置环境也要方便很多.所以,搭建Qt for Andorid也是十分简单的.需要以下工具: 1.最方便的Qt官方包, ...
- [ASE][Daily Scrum]11.24
今天开会总结了一下第一周的进度,讨论了无限地图的访存方法,做了简单的人员调整, Client的包接收分析与服务器通信这块基本上完成了, 之后Jiafan Zhu会开始和Junbei以及Songtao一 ...
- 【Python之路Day12】网络篇之Python操作MySQL
pymysql是Python中操作MySQL的模块,使用方法和MySQLDB几乎一样. 1. 执行SQL语句 #!/usr/bin/env python3 # -*- coding: utf-8 -* ...
- 配置SQL Server去使用 Windows的 Large-Page/Huge-Page allocations
配置SQL Server去使用 Windows的 Large-Page/Huge-Page allocations 目录表->页表->物理内存页 看这篇文章之前可以先看一下下面这篇文章 ...
- 让ASP.NET Web API支持text/plain内容协商
ASP.NET Web API的内容协商(Content Negotiation)机制的理想情况是这样的:客户端在请求头的Accept字段中指定什么样的MIME类型,Web API服务端就返回对应的M ...
- 水火难容:同步方法调用async方法引发的ASP.NET应用程序崩溃
之前只知道在同步方法中调用异步(async)方法时,如果用.Result等待调用结果,会造成线程死锁(deadlock).自己也吃过这个苦头,详见等到花儿也谢了的await. 昨天一个偶然的情况,造成 ...
- 在Linux CentOS上编译CoreCLR
经过几天的努力,终于解决了在CentOS上编译CoreCLR的问题.最终发现问题是CMAKE_C_FLAGS的设置引起的. 只要在“src/pal/tools/clang-compiler-overr ...
- Java-基础练习1
1. Java为什么能跨平台运行?请简述原理. 因为Java程序编译之后的代码不是能被硬件系统直接运行的代码,而是一种“中间码”——字节码.然后不同的硬件平台上安装有不同的Java虚拟机(J ...
- atitit. 日志系统的原则and设计and最佳实践(1)-----原理理论总结.
atitit. 日志系统的原则and设计and最佳实践总结. 1. 日志系统是一种不可或缺的单元测试,跟踪调试工具 1 2. 日志系统框架通常应当包括如下基本特性 1 1. 所输出的日志拥有自己的分类 ...
- paip.c++ 转换 java 解决方案
paip.c++ 转换 java 解决方案 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/a ...