10

我希望Sanctuary提供与Fantasy Land兼容的具有基于值的相等语义的 Map 和 Set 类型。理想情况下,这些值是不可变的,尽管这并不重要,因为 Sanctuary 将提供纯函数来合并和以其他方式操作这些值。

我很想利用Immutable.js团队所做的出色工作;我想实现持久数据结构需要相当大的努力!

Immutable.js 提供的 API 并不重要,因为 Sanctuary 会公开与这些值交互的函数。然而,这些类型的相等语义是至关重要的。

这对我的用例来说是不可接受的:

> Map([[[1, 2, 3], 'foo'], [[1, 2, 3], 'bar']])
Map { [1,2,3]: "foo", [1,2,3]: "bar" }

[1, 2, 3]是相同的值[1, 2, 3]。不可能有两个具有相同键的映射条目。

的处理-0也有问题:

> Immutable.is(Map([[0, 0]]), Map([[-0, -0]]))
true

我意识到可以通过定义方法来定义自己类型的相等语义equals,但我希望重新定义原生类型(例如 Array 和 Number)的相等语义。这可能吗?相关文件似乎是is.js,但我没有看到用于自定义的钩子。

Sanctuary 的 Map 类型可能会包装 Immutable.js 的 Map 类型。这将提供:

  • 一种处理方式-0
  • assoc在执行通常会导致重复键的操作之前执行基于值的相等检查的机会;和
  • 定义各种fantasy-land/方法的地方。

也许:

Map k v = { negativeZero :: Maybe v
          , value :: ImmutableMap k v
          , fantasy-land/equals :: Map k v ~> Map k v -> Boolean
          , fantasy-land/map :: Map k v ~> (k -> a) -> Map a v
          , fantasy-land/bimap :: Map k v ~> (k -> a, v -> b) -> Map a b
          , ...
          }

我想确保在创建上述包装器之前没有其他方法可以实现所需的相等语义。facebook/immutable-js#519并不乐观。

4

1 回答 1

1

尽管很久以前有人问过这个问题,但我没有看到对这个简单解决方案的引用:

const {Map, fromJS} = Immutable

// instead of this:
console.log(
  Map([[[1, 2, 3], 'foo'], [[1, 2, 3], 'bar']]).toString(),
)

// do this:
console.log(
  Map(fromJS([[[1, 2, 3], 'foo'], [[1, 2, 3], 'bar']])).toString()
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/4.0.0-rc.12/immutable.min.js"></script>

通过使用fromJS深度转换对象,您可以获得值相等

于 2018-11-13T22:50:14.500 回答