Promise composition

Added means of composing Promises by using `#zip` an `#flat_map`. Loosely based on scala's `Future#zip` and `Future#flat_map`. I hope I didn't mess up when `#execute` should be called - if I understand correctly in the case of `#zip` the Promises will be scheduled one by one unless someone schedules them all beforehand.
@obrok The `#flat_map` method calls the `#on_fulfill` and `#on_reject` methods of the child. Those methods, in turn, call `#realize`. The `#realize` method calls `#post` on the executor. If you create the child `Promise` here on line 122 without passing an `:executor` option it will cause the child promise to be run on the global thread pool. When you pass in `@executor` the way you do on line 124 you post the `#on_...` method asynchronously to the same executor as the current promise. Both approaches work but they provide different behavior.

I like the approach you currently take because I think it aligns better with the expectations of the user. When I create a promise with a given executor, it's reasonable to expect all children to run on the same executor.

Another option would be to replace line 124 with this:

```ruby
      child = Promise.new(
        parent: self,
        executor: Concurrent::ImmediateExecutor.new
      )
```

An `ImmediateExecutor` will cause the child promise to execute on the current thread. This will create more deterministic behavior for the `#flat_map` function.

I'm not sure which of those options best matches your desired behavior.