facebook / facebook/flow

Generic composition of two generic functions produces a non-generic composed function

Open
#5,847 1 comment 0 reactions 0 assignees View on GitHub
Typing: polymorphism
Dominant language
Rust
Stars
22.3k
Forks
1.9k
PR merge metrics
No merged PRs in 30d

Description

This is a bug, please see it [reproduced on flow.org/try](https://flow.org/try/#0C4TwDgpgBAKuEEEA8A1AfFAvFA3lAhgFxQpQC+A3AFCiSzwBCqG2eARsaZVVQMYD2AOwDOwKAHcATvjAIsUJDDQAKAB7EYASg3xkSrBmV4iUVeU3UBIsVJkN5iletjb6kJvsyH2xM2Qt8QqJQAJYAJg4Akk7Eka6RBqbUgdZQAgC2YPzC0NhICAA0UAxFAMIqAGbE9l5QpUUA5sRytQyuyi0YpZqJas2upQZUUCNQFcoNapoBKcG2sgD64fIZWTnK84WhYQFWc9JgDEsR2KvZEBsHJdsze2KikiGCDS0SBwjHygDkD18Byg8ni8AHQmQHPALgkH4YG8AAW+EkpX4YUQwGUAAZbkExIIAK7pNgQSSvTafACMACYAMz-fGE4kIUHEelEyQBVmM0HA4D8ABiIVUEDCynJWOSdygUJqbzsnx+wEkf2oAMVQIYwI4UrVEOo0s1sIRSJRaMx2NSnMkMvmR3CoppdIJbI1WstHKdxJdPP5guFovFVCAA).

A bit mind twisting, but it's quite simple. A naive parametric `compose2` function type
```javascript
type Compose2 = (B => C, A => B) => (A => C);
```
produces a non-parametric function type. Once it gets called it breaks all the following calls, as they will conflict with all previous calls. Same would happen with an even more naive non-parametric compose function like this:
```javascript
const compose = f => g => x => f(g(x));
```

### Possible workarounds

1. Compose manually as a true Jedi 😌
2. Compose semi-manually using some ugly syntax like this:
```javascript
const f_g = (x: X): $Call => f(g(x))
```
3. Have a handful of differently named compose functions 😂

### What did not help

1. Making more generic types
2. Having 100% flow coverage
3. Typing `compose()` with `$Compose`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.