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. ASP.NET MVC学习之模型绑定(1)

    一.前言 下面我们将开始学习模型绑定,通过下面的知识我们将能够理解ASP.NET MVC模型的模型绑定器是如何将http请求中的数据转换成模型的,其中我们重点讲述的是表单数据. 二.正文 1.简单类型 ...

  2. 编译nginx时提示undefined reference to 'pcre_free_study' 的问题及解决

    ./configure --add-module=../ngx_devel_kit-0.2.19/ --add-module=../lua-nginx-module-0.9.19/  --with-l ...

  3. 用c#开发微信 (10) JS-SDK 基本用法- 分享接口“发送到朋友”

    微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享. ...

  4. 用c#开发微信 (7) 微渠道 - 推广渠道管理系统 2 业务逻辑实现

    我们可以使用微信的“生成带参数二维码接口”和 “用户管理接口”,来实现生成能标识不同推广渠道的二维码,记录分配给不同推广渠道二维码被扫描的信息.这样就可以统计和分析不同推广渠道的推广效果. 上次介绍了 ...

  5. [openwrt 项目开发笔记]: 传送门

    “Openwrt 项目开发笔记”系列传送门: [Openwrt 项目开发笔记]:Openwrt平台搭建(一) (2014-07-11 00:11) [Openwrt 项目开发笔记]:Openwrt平台 ...

  6. 改进ConcurrentDictionary并行使用的性能

    上一篇文章“ConcurrentDictionary 对决 Dictionary+Locking”中,我们知道了 .NET 4.0 中提供了线程安全的 ConcurrentDictionary< ...

  7. 分布式数据库 HBase

    原文地址:http://www.oschina.net/p/hbase/ HBase 概念 HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用 ...

  8. [游戏模版18] Win32 五子棋

    >_<:Learning its AI logic. >_<:resource >_<:code: #include <windows.h> // C ...

  9. PHP将XML转成数组

    如果你使用 curl 获取的 xml data$xml = simplexml_load_string($data);$data['tk'] = json_decode(json_encode($xm ...

  10. javascript 函数详解2 -- arguments

    今天我们接着上篇文章来继续javascript函数这个主题.今天要讲的是函数对像中一个很重要的属性--arguments. 相关阅读: javascript 函数详解1 -- 概述 javascrip ...