Immutable.js数据结构的自定义相等语义

时间:2016-09-18 11:50:16

标签: javascript functional-programming immutable.js sanctuary

我希望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并不乐观。

1 个答案:

答案 0 :(得分: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深度转换对象,您将获得值相等性