jwoudenberg / fantasy-dict

Fantasy-land compatible dictionary.
6 stars 2 forks source link

Considere deep dictionnaries #2

Open rachidbch opened 8 years ago

rachidbch commented 8 years ago

Nice idea and nice execution.

Would you considere implementing dictionnaries of dictionnaries ? Something that would make the following snippet work:

sequence( Maybe.of, Dict({name: Just('me'), address: Dict({street: Just("123 FakeStreet"), city: Just("FakeTown") }), age: Just(18) }))

--> 
Just(Dict({name: 'me', address: Dict({street: "123 FakeStreet", city: "FakeTown" }), age: 18 }))

With that we could have fantasy-land compatibility for all js object literals and not only for flat dictionnaries.

jwoudenberg commented 8 years ago

Hey rachidbch, you can already put dictionaries in dictionaries, but performing sequence on a dictionary is only going to work if all the values in it are of the same type. In your case, the address would need to be wrapped into a maybe to, to get the following dict:

const d = Dict({
  name: Just('me'),
  address: Just(Dict({street: Just("123 FakeStreet")})),
  city: Just("FakeTown"),
  age: Just(18)
});

This you can pass to sequence.

rachidbch commented 8 years ago

Thanks for your answer Jasper and sorry for the delay. Yes of course sequence would pass with your example but it would be so helpfull to have objects of any deep traversable in fantasy-land sense. For instance you could use Ramda's evolve function (or anyother code producing JS objects) to transform the 'person' object above: If transformations are FP protected, a bunch of Right/Left/Just/Nothing values will appear in the transformed object. calling sequence on the transformed person would produce a Right(person) or Just(Person) if everything went ok or a Left(Error) or Nothing is something went wrong.

Actually i strongly suspect fantasy-dict could turn into some sort of transparent wrapper that could give any JS object fantasy-land super-powers: fantasy-entities :) ?

I've played a bit with the concept and created a PR.

rachidbch commented 8 years ago

Hi @jwoudenberg, my explanation above may not be so clear. If you have any hint on how i could clarify that further feel free to ask. The tests in PR #4 are a good place to have a quick overview of the feature.

jwoudenberg commented 8 years ago

Hey, sorry for the slow response. It's nothing to do with your explanation, I just want to take the time to write you a proper response and haven't gotten around to it yet. Is it OK if I get back to you this weekend?

rachidbch commented 8 years ago

Thanks for your answer Jasper. Take your time, there's noting urgent here :) Have a great weekend!

jwoudenberg commented 8 years ago

Hi @rachidbch,

tldr; I believe I see what you're trying to do, but I think a dictionary is the wrong type to do it with. Rather than complicating the implementation of sequence(), I suggest finding / creating a type that better fits your needs, and let the fantasy-land specification do the heavy lifting for you :).`

Longer:

A dictionary is a simple type, mapping certain string keys to arbitrary Values. The dictionary doesn't care what kind of Values that are, nor do I believe it should. Putting recursive logic into the dictionary type thus feels like the wrong approach to me, instead I believe it makes more sense to use a type that is recursive in nature.

If you want to warp an arbitrary JSON-like Value into a fantasy-land type, a dictionary does not seem strong enough. I think you'd need to put the recursive nature into the data-type itself, defining it perhaps something like this:

type Object = Dictionary Object | List Object | Value

So basically a tree with two type of node constructors (Dictionary and List) and one type of leave (Value). Your example data structure expressed in this type could look something like this:

// Wrap your js object into an Object:
const obj = Object.fromJS({
  name: Object.Just('me'),
  address: Object.Dictionary({
    street: Just("123 FakeStreet"),
    city: Just("FakeTown")
  }),
  age: Just(18)
});

console.log(obj);
// =>
// Object.Dictionary({
//   name: Object.Value(Just('me')),
//   address: Object.Dictionary({
//     street: Object.Value(Just("123 FakeStreet")),
//     city: Object.Value(Just("FakeTown"))
//   }),
//   age: Object.Value(Just(18))
// });

console.log(sequence(Maybe.of, obj));
// =>
// Just(Object.Dictionary({
//   name: Object.Value('me'),
//   address: Object.Dictionary({
//     street: Object.Value("123 FakeStreet"),
//     city: Object.Value("FakeTown")
//   }),
//   age: Object.Value(18)
// }));
rachidbch commented 8 years ago

Sorry @jwoudenberg for beeing so slow: august is not the best month for reactivity :) I'll come back to you next week as I'll be fully back to work then. By the way I'd like to thank you for the time you took for your detailed and argumented answer ...