1

以下代码是用 javascript 编写的。

这个问题涉及尝试深入研究某种类别理论,也许哈斯克尔或更熟悉这个问题的数学方面的人可以帮助我?

我试图围绕这样一个想法,即仿函数是保留结构的类别之间的映射。更具体地说-根据我的理解-编程语言中的函子是内函子。这意味着编程语言中的函子是将类型和函数映射到编程语言中通常定义的更广泛的类型和函数类别中的子类别的态射。

据我所知,函子(或内函子)还必须遵守某些通过促进组合和同一性来保护结构的定律。

我发现几乎不可能创建一个我认为保留结构并遵守函子定律的函子。再加上我只是认真地用 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 上下文中,然后添加一个,它会给我一个 null 的 noEvens。但是,如果我先将一个偶数加一,然后再提升结果,则会产生一个奇数的 noEvens。

根据我的理解,这两条路径都应该在函子定律下通勤。它们显然不会,因为通过每个上下文的相同映射在被提升后不会产生相同的结果“noEvens.of(value)”。

所以我想我的问题是,这是否意味着这不是函子?这种情况(类型或其他)是什么让它表现得很奇怪?

我想我只是感到困惑,因为似乎所有“noEvens”所做的都是将值提升到一个不存在偶数的新上下文(子类别,无论如何),但很明显某些途径不会通勤。

我发现将值“提升”到新的映射上下文中的想法非常直观,它为您提供了很多机会来处理条件,而无需实现大量冗余代码。但我不想假装我遵守某种形式化的“函子定律”系统。

我在分析这种情况时遗漏了什么类型系统和函子定律?

4

1 回答 1

1

除了我的评论...

你可能会注意到你的几乎函子类也不满足恒等律。

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 作为一个概念,在其核心,不能是一个服从合成法则的函子。

于 2018-02-25T05:31:58.120 回答