Although fluture-js#401 solved the case for using `map` on a `ConcurrentFutureInstance`, it broke `FutureInstance#pipe(map(...))`:
```typescript
import { ConcurrentFutureInstance, FutureInstance, map } from 'fluture';
declare const x: FutureInstance<Error, number>;
declare const y: ConcurrentFutureInstance<Error, number>;
declare const double: (x: number) => number;
const v1 = map(double)(x); // ok; FutureInstance<Error, number>
const v1p = map(double)(y); // ok; ConcurrentFutureInstance<Error, number>
const v2 = x.pipe(map(double)) // error
```
This could potentially be down to TypeScript selecting the wrong overload (maybe because `ConcurrentFutureInstance` is the more restrictive type?)
So, I came up with this version instead, which uses a Conditional type to represent the mapper function instead. It's not ideal from an ergonomics perspective, as you end up with the whole conditional type appearing in Intellisense information. I've never been fond of that. But, it does fix (and preserve all type information) for the three forms above:
```typescript
import { ConcurrentFutureInstance, FutureInstance, /*map*/ } from 'fluture';
declare function map<RA, RB>(mapper: (value: RA) => RB): <T>(source: T) =>
T extends FutureInstance<infer U, infer V> ?
FutureInstance<U, V> :
T extends ConcurrentFutureInstance<infer U, infer V> ?
ConcurrentFutureInstance<U, V> :
never;
declare const x: FutureInstance<Error, number>;
declare const y: ConcurrentFutureInstance<Error, number>;
declare const double: (x: number) => number;
const v1 = map(double)(x); // ok; FutureInstance<Error, number>
const v1p = map(double)(y); // ok; ConcurrentFutureInstance<Error, number>
const v2 = x.pipe(map(double)) // ok; FutureInstance<Error, number>
```
I did also experiment with simply swapping the order of the overloads around:
```typescript
import { ConcurrentFutureInstance, FutureInstance, /*map*/ } from 'fluture';
declare function map<RA, RB>(mapper: (value: RA) => RB): {
<L>(source: ConcurrentFutureInstance<L, RA>): ConcurrentFutureInstance<L, RB>;
<L>(source: FutureInstance<L, RA>): FutureInstance<L, RB>;
}
declare const x: FutureInstance<Error, number>;
declare const y: ConcurrentFutureInstance<Error, number>;
declare const double: (x: number) => number;
const v1 = map(double)(x); // ok; FutureInstance<Error, number>
const v1p = map(double)(y); // ok; ConcurrentFutureInstance<Error, number>
const v2 = x.pipe(map(double)) // almost ok; FutureInstance<unknown, number>
```
Observe that the left type of `v2` is `unknown` when it should be `Error`. I suspect this is down to that hanging `<L>` type parameter, and the only way to eliminate that (afaik) is to use a conditional type instead. Which, coincidentally, is where we came in.