Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

函子和范畴(组合软件) #103

Open
zzz6519003 opened this issue May 14, 2017 · 6 comments
Open

函子和范畴(组合软件) #103

zzz6519003 opened this issue May 14, 2017 · 6 comments

Comments

@zzz6519003
Copy link
Owner

http://mp.weixin.qq.com/s/vw_FCdnBpWbxBxXONu0zAg

const Identity = value => ({map: fn=>Identity(fn(value))});
undefined
Identity
value => ({map: fn=>Identity(fn(value))})
const trace = x=> {console.log(x) return x;}
VM948:1 Uncaught SyntaxError: Unexpected token return
const trace = x=> {console.log(x)
return x;}
undefined
const u = Identity(2);
undefined
u
Object {map: function}
u.map(trace);
VM951:1 2
Object {map: function}map: fn=>Identity(fn(value))__proto__: Object
u.map(x=>x).map(trace);
VM951:1 2
Object {map: function}
const f = n => n + 1;
undefined
const g = n => n * 2;
undefined
const r1 = u.map(x=>f(g(x)));
undefined
const r2 = u.map(g).map(f);
undefined
r1.map(trace)
VM951:1 5
Object {map: function}
r2.map(trace)
VM951:1 5
Object {map: function}

const Identity2 = value=> ({map: fn => Identity2(fn(value)), valueOf: () => value,});
undefined
const ints = (Identity2(2) + Identity2(4))
undefined
trace(ints)
VM951:1 6
6
const hi = (Identity2('h') + Identity2('i'))
undefined
trace(hi)
VM951:1 hi
"hi"
const Identity3 = value=> ({map: fn => Identity2(fn(value)), valueOf: () => value, toString: () => `Identity($(value))`});
undefined
const Identity3 = value=> ({map: fn => Identity3(fn(value)), valueOf: () => value, toString: () => `Identity($(value))`});
VM1471:1 Uncaught SyntaxError: Identifier 'Identity3' has already been declared
    at <anonymous>:1:1
(anonymous) @ VM1471:1
const Identity4 = value=> ({map: fn => Identity4(fn(value)), valueOf: () => value, toString: () => `Identity4($(value))`,
[Symbol.iterator]: () => {
let first = true;
return ({
next: () => {
if (first) {
first = false;
return ({
done: false,
value
});
}
return ({
done: true
});
}
});
}});

const arr3 = [6,7,...Identity4(8)];
undefined
trace(arr3)
VM951:1 (3) [6, 7, 8]0: 61: 72: 8length: 3__proto__: Array(0)
(3) [6, 7, 8]0: 61: 72: 8length: 3__proto__: Array(0)
typeof trace(arr3)
VM951:1 (3) [6, 7, 8]
"object"
@zzz6519003
Copy link
Owner Author

在 Haskell中,函子类型被定义为:

fmap :: (a -> b) -> f a -> f b
给出一个函数,该函数有一个参数 a,并返回一个 b 和一个有零到多个 a 在其中的函子:fmap 返回一个其中有零到多个 b 的盒子。f a 和 f b 位可以被读为 a 的函子和 b 的函子,意思是 f a 的盒子中有 a,f b 的盒子中有 b。

使用函子很简单 - 只要调用 map() 即可:

const f = [1, 2, 3];
f.map(double); // [2, 4, 6]

@zzz6519003
Copy link
Owner Author

恒等
如果将恒等函数(x => x)传递给 f.map(),这里 f 是任何函子,那么结果应该等价于 f(即与 f 有相同含义):

const f = [1, 2, 3];
f.map(x => x); // [1, 2, 3]

@zzz6519003
Copy link
Owner Author

下面我们用 JavaScript 再看看组合:

给出一个函子 F:

const F = [1, 2, 3];
如下的语句都是等同的:

F.map(x => f(g(x)));

// 等同于...

F.map(g).map(f);

@zzz6519003
Copy link
Owner Author

很多函数式编程术语都来自于范畴学,范畴学的精髓就是组合。范畴学是最开始很可怕,但是很简单,就像从跳水板跳下或者坐过山车一样。

@zzz6519003
Copy link
Owner Author

// trace() 是一个让我们更容易检测内容的实用程序
const trace = x => {
  console.log(x);
  return x;
};

const u = Identity(2);

// 恒等定律
u.map(trace); // 2
u.map(x => x).map(trace); // 2

const f = n => n + 1;
const g = n => n * 2;

// 组合定律
const r1 = u.map(x => f(g(x)));
const r2 = u.map(g).map(f);

r1.map(trace); // 5
r2.map(trace); // 5

@zzz6519003 zzz6519003 pinned this issue Feb 23, 2020
@zzz6519003
Copy link
Owner Author

函子之所以牛叉,是有很多原因的。最重要的是,它们是一种抽象,我们可以用它们以作用于任何数据类型的方式来实现很多有用的事情。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant