Consider the following code (flow 0.27):
interface Functor<A> {
map<B>(fn:(a:A) => B):Functor<B>;
}
declare function map<T,R>(fn:(x:T) => R, xs:Functor<T>):Functor<R>;
map(x => x + 1, [1, 2, 3]);
Running this outputs:
[No file]:0
inconsistent use of library definitions
module. *** Recursion limit exceeded ***
module
Found 1 error
Given that Array should structurally implement Functor, I would expect this to pass.
Uh oh! This should never happen鈥攕omething is causing a loop in the type checker. Will investigate ASAP. Thanks a lot for the report!
The above can be simplified to:
// @flow
interface Functor<A> {
map<B>(fn:(a:A) => B):Functor<B>;
}
const a = [1];
(a:Functor<number>);
To get flow to pass, we can do:
// @flow
interface Functor<A> {
map<B>(fn:(a:A) => B):Array<B>;
}
const a = [1];
(a:Functor<number>);
That seems to imply that it doesn't match well on the return of map being Functor.
Another way of writing the interface:
// @flow
interface Functor<A> {
map<B, F:Functor<B>>(fn: (a:A) => B): F
}
const a = [1];
(a:Functor<number>);
This outputs: *** Recursion limit exceeded *** but also outputs the following error:
inconsistent use of library definitions
201: map<U>(callbackfn: (value: T, index: number, array: Array<T>) => U, thisArg?: any): Array<U>;
^^^^^^^^ array type. This type is incompatible with. See lib: /private/tmp/flow/flowlib_34da7a76/core.js:201
201: map<U>(callbackfn: (value: T, index: number, array: Array<T>) => U, thisArg?: any): Array<U>;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ some incompatible instantiation of `F`. See lib: /private/tmp/flow/flowlib_34da7a76/core.js:201
Nice catch @jgrund. Support for functors is something we definitely need in our code base, we use flow heavily in our project.
Most helpful comment
Uh oh! This should never happen鈥攕omething is causing a loop in the type checker. Will investigate ASAP. Thanks a lot for the report!