Natural Transformations, let's explain it by using a coding example, for example, we have a 'Either' holding a value 'a' and we want to transform a' Task' that holding an 'a'.

  1. // Either(a) -> Task(a)

Let's start coding:

  1. const Either = require('data.either');
  2. const {Right, Left, fromNullable} = Either;
  3. const Task = require('data.task');
  4.  
  5. const eitherToTask = e =>
  6. e.fold(Task.rejected, Task.of);
  7.  
  8. eitherToTask(Right('Good')).fork(
  9. e => console.error('err', e),
  10. x => console.log('res', a)
  11. ) // 'res' Good

Let's go thought:

  1. const eitherToTask = e =>
  2. e.fold(Task.rejected, Task.of);

'Either' has 'fold' method (left, right), as we know 'fold' will unbox the contianer just return the value, so that it will unbox the 'Either' type, and we wrap the return value with 'Task'. So now, 'eitherToTask' return a 'Task'

  1. eitherToTask(Right('Good')).fork(...)

The result we using 'Right' instead of 'Left' we will explain later, but here, we know we have a 'Task', therefore we can call 'fork' to trigger the side effect.

Law:

natural_transform(Functor).map(function) === natural_transform(Functor.map(function))

On the left side of equals, we have natural transform function wraps a Functor, then map to a function.

On the right side, we have a natural transform function wrap functor that map to a funciton.

Let's see an example:

  1. const Box = x => ({
  2. map: f => Box(f(x)),
  3. fold: f => f(x)
  4. })
  5.  
  6. const boxToEither = b =>
  7. b.fold(Right);
  8.  
  9. const res1 = boxToEither(Box()).map(x => x * );
  10. console.log(res1); // Either (200)
  11. const res2 = boxToEither(Box().map(x => x * ));
  12. console.log(res2); // Either (200)

What if we using 'Left' instead of 'Right':

  1. const Box = x => ({
  2. map: f => Box(f(x)),
  3. fold: f => f(x)
  4. })
  5.  
  6. const boxToEither = b =>
  7. b.fold(Left);
  8.  
  9. const res1 = boxToEither(Box()).map(x => x * );
  10. console.log(res1); // Either(100)
  11. const res2 = boxToEither(Box().map(x => x * ));
  12. console.log(res2); // Either(200)

As we can see 'res1' is no longer equals to 'res2', because Left will ingore mapping function.

Another example: List -> Either:

  1. // first :: [] -> Either
  2. const first = xs => fromNullable(xs[]);
  3. const res3 = first([,,]).map(x => x +);
  4. const res4 = first([,,].map(x => x +));
  5. console.log(res3); // Either(2)
  6. console.log(res4); // Either(2)

These two shall be equal and they are. Any function that satisfies this equation is a natural transformation. Let's look at this on the board here.

If we have some F(a) and some functor holding an a and we map(f) over it, it transforms that a to a b. we're just mapping a function from the type a to some type b here all inside our functor f. Then we run a natural transformation we'll have a G(b).

If we take the other path moving downward we'll first naturally transform our functor holding an a into the G(a) here, and then we map(f) over that to get a G(b). We end up with the same result. This can be quite useful.

[Compose] 20. Principled type conversions with Natural Transformations的更多相关文章

  1. [Compose] 21. Apply Natural Transformations in everyday work

    We see three varied examples of where natural transformations come in handy. const Right = x => ( ...

  2. A Tour of Go Type conversions

    The expression T(v) converts the value v to the type T. Some numeric conversions: var i int = 42 var ...

  3. Type conversions in C++类型转换

    ###Implicit conversions隐式转换* 可以在基本类型之间自由转换:* 可以把任何类型的pointer转换为void pointer:* 可以将子类pointer转换为基类point ...

  4. C语言 结构体指针赋值 incompatible types when assigning to type 'char[20]' from type 'char *'

    strcpy(pstudent->name, "guo zhao wei "); 为什么错误,该怎么写,(红色行)     追问 为什么不能直接赋值啊, 追答 用char n ...

  5. 条款24:若所有参数皆需要类型转换,请为此采用non-member函数(Declare non-member functions when type conversions should apply to all parameters)

    NOTE: 1.如果你需要为某个函数的所有参数(包括this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.

  6. C++: Type conversions

    1.static_cast     static_cast可以转换相关联的类,可以从子类转换成父类.也能从父类转向子类,但是如果转换的父类指针(或者父类引用)所指向的对象是完整的,那么是没有问题:但是 ...

  7. Type Systems

    This section deals with more theoretical aspects of types. A type system is a set of rules used by a ...

  8. python3.4 data type

    #coding=utf-8 #Python 3.4 https://docs.python.org/3.4/library/ #IDE:Eclipse +PyDev Window10 import a ...

  9. 转载:oracle 自定义类型 type / create type

    标签:type create oracle object record 一:Oracle中的类型有很多种,主要可以分为以下几类: 1.字符串类型.如:char.nchar.varchar2.nvarc ...

随机推荐

  1. [PHP-Socket] Socket Programming in PHP

    Simple Client-Server socket program in PHP Introduction Sockets are used for interprocess communicat ...

  2. gvim 备份文件去除 配置

    默认情况下使用Vim编程,在修改文件后系统会自动生成一个带~的备份文件,看上去又乱又讨人厌. 怎么让Vim不自动生成这些备份文件呢? 1. 找到你的Vim安装目录,如果是在Windows下默认路径安装 ...

  3. 设计模式之美:Composite(组合)

    索引 意图 结构 参与者 适用性 缺点 效果 相关模式 实现 实现方式(一):在 Component 中定义公共接口以保持透明性但损失安全性. 意图 将对象组合成树形结构以表示 “部分-整体” 的层次 ...

  4. 转载:SQL Server 2008-建立分区表(Table Partition) 转载

    数据库结构和索引的是否合理在很大程度上影响了数据库的性能,但是随着数据库信息负载的增大,对数据库的性能也发生了很大的影响.可能我们的数据库在一开始有着很高的性能,但是随着数据存储量的急速增长—例如订单 ...

  5. 由Memcached使用不当而引发性能问题的两个经验总结

    在这个cache everywhere的时代,在这个人人都会说分布式缓存的时代,Memcached几乎已成为网站开发中的标配. 作为一名普通的coder,我们在编写缓存代码的时候,很多情况下可能都只是 ...

  6. ubuntu14.04中文楷体变默认字体

    使用ubuntu以来,最让人头疼的事情就是在英文系统里面使用中文,一般中文字体都很难看,要么有锯齿,要么就是楷体.经过网上搜索找到一堆方法.一个个尝试之后觉得以下方式是最简单有效的. 1.安装font ...

  7. Nagios学习笔记四:基于NRPE监控远程Linux主机

    1.NRPE简介 Nagios监控远程主机的方法有多种,其方式包括SNMP.NRPE.SSH和NCSA等.这里介绍其通过NRPE监控远程Linux主机的方式. NRPE(Nagios Remote P ...

  8. paip.提升性能---jvm java 工具使用.

    paip.提升性能---jvm java 工具使用. 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn ...

  9. iOS开发——高级技术&iCloud服务

    iCloud服务 iCloud 是苹果提供的云端服务,用户可以将通讯录.备忘录.邮件.照片.音乐.视频等备份到云服务器并在各个苹果设备间直接进行共享而无需关心数据同步问题,甚至 即使你的设备丢失后在一 ...

  10. Java 线程 — synchronized、volatile、锁

    线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...