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
assocoperation 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.
Map. I always tend to accept the limitations of JS. Moreover I doubt that objects used as keys inMaps really benefit from persistent data structures, since they ought to be rather small, like value objects. Immutable.js seems to be more suitable for huge data structures like a redux store.ArrayandNumber? Modifying such a crucial property of builtins could be devastating.Array.prototype.equalsandNumber.prototype.equalswould solve the problem.ArrayandNumberwhich defines your custom.equalsmethod, and then to instantiate the wrapper implicitly for all arrays and numbers that are passed into your wrappedMap.