Skip to content

Instantly share code, notes, and snippets.

@Bannerets
Last active July 1, 2022 12:33
Show Gist options
  • Save Bannerets/07a71802e3468d252924091a65ac2b3c to your computer and use it in GitHub Desktop.
Save Bannerets/07a71802e3468d252924091a65ac2b3c to your computer and use it in GitHub Desktop.
Contravariant predicates in JavaScript + Flow with correct type inference
// https://flow.org/try/#0FA4FwTwBwUwAgAoCcYBMBiA7APAWgCoB8cAvHPqcQEYD2NANjAIaYgDG9TAzl3AMI1MYJE2Ro8ROAG9gcOAGooALkQoMOIgG5ZcHW0FdhAVzZgaSOAAplqtFmxEAlNLhgAFgEsuAOiik4fgC+IHIA5jBgYqiWjipR9pJScChgRkiYrp4+QTp6gsJMALZMUA4AjISWAGaYKvhllOSx-PkiUeXEMnJyKWkZmDAA7i1CbWqWAB6N7l6+1ZiTjks6wcHAAPTrcACqXEzhSsD6mIZwXgCiAG4wGWQDwwKjouNTJMRTAKRwAEykJGQABmcmxGBXamCMhSoMCQhCOBjAZy4VxuAGVhP4LtdMN5jgVilBrEwkFwYABJITAraPMFqbCGJAeTChOHHU5QNSY5HY9FIbzhSLjKm2dT04RMlnwk6I2gMfwctCWADk3yVjilXAYMG89BooUssvoVLeriQRhgQA
// Contravariant functor.
// type Contravariant<-T> = {
// contramap<T1>(fn: (T1) => T): Contravariant<T1>
// }
// See also https://github.com/fantasyland/fantasy-land#contravariant
type PredFn<-T> = T => boolean
class ContraPred<-T> {
+p: PredFn<T>;
constructor (p: PredFn<T>) { this.p = p }
getPred(): PredFn<T> { return this.p }
contramap<T1>(fn: T1 => T): ContraPred<T1> {
return new ContraPred(x => this.p(fn(x)))
}
}
// Usage:
const isEven = new ContraPred(x => x % 2 === 0) // ContraPred<number>
const isEvenStr = isEven.contramap(parseInt) // ContraPred<string>
const pred = isEvenStr.getPred() // PredFn<string>
const bool = pred('2')
console.log(bool) //=> true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment