2016-07-29 7 views
0

Ich habe eine Bibliothek von Hilfsfunktionen, die ich Curry-Versionen von exportieren möchte.Problem beim Export Curry generische Funktion

Ein kleines Stück davon sieht wie folgt aus:

export function curry2<A,B,C>(f: (x: A, y: B) => C): (x: A) => (y: B) => C { 
    return (a) => (b) => f(a, b) 
} 

function _push<A>(item: A, items: Array<A>): Array<A> { 
    return items.concat(item) 
} 

export const push = curry2(push) 

Aber das funktioniert nicht. Flow klagt Ausdruck curry2(push) und sagt:

- type parameter 'A' of function call. Missing annotation. 
- type parameter 'B' of function call. Missing annotation. 

Also habe ich versucht, dies zu beheben, indem Sie die exportierte Kennung mit Anmerkungen versehen:

export const push<A>: (item: A) => (items: Array<A>) => Array<A> 

Aber das funktioniert nicht, weil const Ausdrücke nicht generischen Typ Variablen einführen können.

Also dachte ich, ich hätte eine tatsächliche Funktion exportieren, um die Lage sein, es zu annotieren:

export function push<A> (item: A): (items: Array<A>) => Array<A> { 
    return curry2(_push)(item); 
} 

Aber an diesem Punkt werde ich im Grunde neu schreiben ein großes Stück Curry für jede Funktion, die ich exportieren möchte.

Gibt es eine bessere Möglichkeit, Flow zu helfen, die generischen Variablen des Exports in const auszudrücken?

Antwort

2

hier meine Antwort auf die gleiche Frage Siehe: https://github.com/facebook/flow/issues/2165#issuecomment-236868389

Die Hauptbeschränkung hier ist, dass Flow polymorphe Typen überhaupt nicht ableitet . Insbesondere wenn ein Aufruf einer polymorphen Funktion erkannt wird, instantiiert er sofort die Typparameter mit Argumenten vom Typ "Neu", und das Ergebnis wird niemals wie bei Hindley-Milner-Systemen (https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system) "verallgemeinert". Der Grund für diese Einschränkung ist, dass diese Art der polymorphen Typinferenz unentscheidbar ist mit Subtyping (siehe Pierce, "Begrenzte Quantifizierung ist unentscheidbar", POPL'92), und Subtyping ist ein notwendiges Merkmal für JavaScript (aber nicht so sehr für eine ML-ähnliche Sprache).

0

Ich vermute, ist nicht möglich, eine curry2 Funktion ohne höhere kinded Typen

type Function2<A, B, C> = (a: A, b: B) => C; 
type CurriedFunction2<A, B, C> = (a: A) => (b: B) => C; 

export function curry2<A, B, C>(f: Function2<A, B, C>): CurriedFunction2<A, B, C> { 
    return (a: A) => (b: B): C => f(a, b) 
} 

export const push = curry2(function <A>(item: A, items: Array<A>): Array<A> { 
    return items.concat(item) 
}) 

Die letzte Definition zu definieren, bedeutet, dass push Typ hat

push: CurriedFunction2<A, Array<A>, Array<A>> // <= higher kinded type? 
+0

Dies scheint das gleiche Problem zu haben. Das exportierte 'push' sagt, es fehlen Annotationen für die Typparameter A, B und C. Und da es eine const-Deklaration ist, gibt es keine Möglichkeit, sie bereitzustellen. – Adam

+0

Ich meinte, das ist im Moment nicht möglich, Flow unterstützt keine höheren Typen – gcanti