Custom equality semantics for Immutable.js data structures

风格不统一 提交于 2019-12-06 23:27:41

问题


I would like Sanctuary to provide Fantasy Land -compatible Map and Set types with value-based equality semantics. Ideally these values would be immutable, though this is not critical since Sanctuary would provide pure functions for merging and otherwise manipulating these values.

I would love to leverage the good work done by the Immutable.js team; I imagine implementing persistent data structures takes considerable effort!

The API provided by Immutable.js is of little importance since Sanctuary would expose functions for interacting with these values. The equality semantics of these types, though, are crucial.

This is unacceptable for my use case:

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

[1, 2, 3] is the same value as [1, 2, 3]. It should not be possible to have two map entries with the same key.

The handling of -0 is also problematic:

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

I realize it's possible to define the equality semantics of one's own types by defining equals methods, but I wish to redefine the equality semantics of native types such as Array and Number. Is this possible? The relevant file appears to be is.js, but I see no hooks for customization.

It's possible that Sanctuary's Map type could wrap the Immutable.js Map type. This would provide:

  • a way to handle -0;
  • an opportunity to perform value-based equality checks before performing an assoc operation which would normally result in a duplicate key; and
  • a place to define the various fantasy-land/ methods.

Perhaps:

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
          , ...
          }

I'd like to be sure there's no other way to attain the desired equality semantics before creating wrappers such as the above. facebook/immutable-js#519 isn't promising.


回答1:


Although this was asked long ago I don't see a reference to this simple solution:

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>

By deeply converting the objects using fromJS you get the value equality



来源:https://stackoverflow.com/questions/39557342/custom-equality-semantics-for-immutable-js-data-structures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!