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的更多相关文章

  1. [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 ...

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

  3. JDK8新特性 -- Function接口: apply,andThen,compose

    1 Function<T, R>中的T, R表示接口输入.输出的数据类型. R apply(T t) apply: .例子:func是定义好的Function接口类型的变量,他的输入.输出 ...

  4. [转]Neural Networks, Manifolds, and Topology

    colah's blog Blog About Contact Neural Networks, Manifolds, and Topology Posted on April 6, 2014 top ...

  5. 壁虎书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 ...

  6. 2020你还不会Java8新特性?

    Java8(1)新特性介绍及Lambda表达式 前言: 跟大娃一块看,把原来的电脑拿出来放中间看视频用 --- 以后会有的课程 难度 深入Java 8 难度1 并发与netty 难度3 JVM 难度4 ...

  7. [转载] 首席工程师揭秘:LinkedIn大数据后台是如何运作的?(一)

    本文作者:Jay Kreps,linkedin公司首席工程师:文章来自于他在linkedin上的分享:原文标题:The Log: What every software engineer should ...

  8. [Javascript] Functor law

    Functor laws: 1. Identity: map(id) == id 2. Composition: compose(map(f), map(g)) == map(compose(f,g) ...

  9. Category Theory: 01 One Structured Family of Structures

    Category Theory: 01 One Structured Family of Structures 这次看来要放弃了.看了大概三分之一.似乎不能够让注意力集中了.先更新吧. 群的定义 \( ...

随机推荐

  1. wamp链接mysql数据库

    一:链接到自带的数据库 1.打开mysql命令行 密码为空即回车2.输入use mysql 3.执行 update user set password=PASSWORD('123456') where ...

  2. Linux sort 多字段分组排序

    常用参数: -t: 指定分隔符 -k: 指定域 -u: 去除重复行 -n: 以数值排序 -r: 降序排序 (sort默认的排序方式是升序) -o: 结果重定向输出到文件 1.源文件: # cat hh ...

  3. 数据库知识整理<三>

    保证数据的完整性: 3.1数据完整性概述: 数据完整性的意义:我们知道数据库能防止储存垃圾数据,RDBMS实现该功能主要是通过维护数据完整性来实现的.根据数据完整性实施方法我们将其分为四类:实体完整性 ...

  4. t-sql或mssql怎么用命令行导入数据脚本

    osql简单用法:用来将本地脚本执行,适合sql脚本比较大点的情况,执行起来比较方便 osql -S serverIP -U sa -P 123 -i C:\script.sql serverIP数据 ...

  5. Entity Framework 4 数据事务操作

    利用数据库链接进行事务操作 var db = ConnectionHelper.GetConn(ConnectionType.Write);//获取上下文 var conn = db.Connecti ...

  6. MongoDB 基础命令使用学习记录

    1. 启动 mongod 几个常用命令说明:--dbpath : 指定数据库相关文件的存储目录 --logpath: 指定日志文件的存储目录 --port: 指定数据库的端口,默认是 27017 -- ...

  7. Nhibernate基础使用教程以及简易封装

    1.Nhibernate简介 NHibernate是一个面向.NET环境的对象/关系数据库映射工具.对象/关系数据库映射(object/relational mapping,ORM)这个术语表示一种技 ...

  8. 深入浅出OOP(四): 多态和继承(抽象类)

    在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. Abstract Classes 在微软的 ...

  9. C++ 关联容器

    <C++ Primer 4th>读书笔记 关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素. 关联容器(Ass ...

  10. Maven之Hello World入门实例

    1.使用eclipse创建maven工程在eclipse中,选择新建工程的时候,选择other,找到maven 下一步,下一步,直到出现类似如下图片点击finish即可完成maven工程创建. 运行的 ...