以下代码是用javascript编写的。
这个问题涉及尝试进入某些类别理论的尝试,也许是散客或更熟悉这个问题的数学方面的人可以帮助我?
我正在尝试将函子视为保留结构的类别之间的映射这一想法。更具体地说-根据我的理解-编程语言中的函子是endofunctor。这意味着编程语言中的函子是语态,其将类型和功能映射到编程语言中通常定义的更广泛的类型和功能类别中的子类别。
据我所知,函子(或内函子)还必须遵守某些法律,这些法律通过促进组成和特性来保护结构。
我发现几乎不可能创建我认为能保留结构并遵守函子定律的函子。我还只是认真地对javascript进行了编程,这使事实更加复杂,所以类型理论是我从未真正考虑过的东西(毕竟JS是无类型的)。
我做了一个简单的示例,将整数提升到一个最小的上下文中,在该上下文中,映射对偶数不起作用。换句话说,您可以根据自己的构图进行映射,但是一旦您击中一个偶数,该节目即告结束。
看起来有点像Maybe:
class noEvens {
constructor(x) {
this._val = x;
}
static of(x) {
return new noEvens(x);
}
isEven() {
return this._val % 2 === 0;
}
map(projF) {
return this.isEven() ? noEvens.of(null) : noEvens.of(projF(this._val));
}
}
但是很明显,在某些情况下,这不能与应用于普通JS类别中整数的合成相抵消。考虑一个简单地将一个加到一个整数的投影函数。
如果我将一个偶数提升到此noEvens上下文中,然后再加上一个,它将使我的noEvens为null。但是,如果我先将偶数加一个,然后求和,结果将是一个奇数的noEvens。
根据我的理解,这两种途径都应该根据函子定律进行交换。它们显然不是因为在每个上下文中的相同映射在解除后不会导致相同的结果“ noEvens.of(value)”。
所以我想我的问题是,这是否意味着它不是函子?导致这种情况奇怪的是什么类型的情况?
我想我只是感到困惑,因为似乎所有“ noEvens”所做的只是将值提升到一个甚至没有数字的新环境(子类别,无论如何)中,但是很显然某些途径不会通勤。
我发现“提升价值”到新的映射上下文中的想法非常直观,它为您提供了很多处理条件的机会,而无需实现大量的冗余代码。但是我不想以虚假的名义这样做,因为我坚持某种形式的“ functor law”制度。
我在分析这种情况时缺少的类型系统和函子定律是什么?
最佳答案
除了我的评论...
您可能会注意到,您几乎要死的班级也不符合身份法。
const id = x => x;
new noEvens(2).map(id) // != new noEvens(2)
我首先想到的是,错误是允许首先构造包含偶数的noEvens对象。如果isEven检查是在构造函数中完成的,则可以满足ID律。
class noEvens {
constructor(x) {
if (x % 2 === 0) {
this._val = null;
} else {
this._val = x;
}
}
static of(x) {
return new noEvens(x);
}
map(projF) {
if (this._val === null) {
return noEvens.of(null);
}
return noEvens.of(projF(this._val));
}
}
const id = x => x;
new noEvens(1).map(id)._val // ok: 1
new noEvens(2).map(id)._val // ok: null
但是,事实证明该解决方案仍不满足组成定律。
const plusOne = x => x + 1;
// fmap f . fmap g == fmap (f . g) ?
new noEvens(1).map(plusOne).map(plusOne)._val // null
new noEvens(1).map(x => plusOne(plusOne(x)))._val // 3
因此,最终我认为致命的缺陷是noEvens限制了它可以保存的数据类型。正如Bergi所说,“一个普通的仿函数将能够包含任何任意数据。”因此,noEvens作为概念的核心不能成为遵循合成定律的函子。
关于javascript - 了解仿函数定律:这是仿函数吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48958881/