2016-11-12 4 views
2

Ich versuche, eine getippte Version von React als Übung in Ocaml zu machen. Um es funktionaler zu machen, gebe ich einen Datensatz als Argument zum Rendern.Ocaml falscher Typ Inferenz

type ('props,'state) reactInstance = 
    { 
    props: 'props; 
    state: 'state; 
    updater: 'a . ('props,'state) reactInstance -> 'a -> 'state -> unit;} 
and ('props,'state) reactClass = 
    { 
    getInitialState: unit -> 'state; 
    render: ('props,'state) reactInstance -> element;} 

module type ComponentBluePrint = 
    sig 
    type props 
    type state 
    val getInitialState : unit -> state 
    val render : (props,state) reactInstance -> element 
    end 

module type ReactClass = 
    sig 
    type props 
    type state 
    val mkUpdater : 
    props -> 
    ((props,state) reactInstance -> 'e -> state) -> 
     (props,state) reactInstance -> 'e -> unit 
    val reactClass : (props,state) reactClass 
    end 

module CreateComponent(M:ComponentBluePrint) = 
    (struct 
    include M 
    let rec mkUpdater props f i e = 
     let nextState = f i e in 
     let newInstance = 
     { props; state = nextState; updater = (mkUpdater props) } in 
     () 

    let reactClass = 
     { render = M.render; getInitialState = M.getInitialState } 
    end : (ReactClass with type props = M.props and type state = M.state)) 

Eine Sache, die ich nicht verstehe ist, warum der Compiler kann nicht die Art von updater = (mkUpdater props) in let newInstance = { props; state = nextState; updater = (mkUpdater props) } schließen.

Error: Signature mismatch: 
     Values do not match: 
     let mkUpdater : 
    props => 
    (reactInstance props state => '_a => '_b) => 
    reactInstance props state => '_a => unit 
     is not included in 
     let mkUpdater : 
    props => 
    (reactInstance props state => 'e => state) => 
    reactInstance props state => 'e => unit 

Was ist der Unterschied zwischen '_a und' e? Es sieht genau dasselbe für mich. Wie kann ich diesen Typ prüfen?

+0

Der Fehler, den Sie angegeben haben, ist nicht der Fehler, den Ihre Datei erzeugt. Der richtige Fehler ist "Fehler: Dieser Ausdruck hat Typ ('a ->' b -> 'c) ->' a -> 'b ->' d aber ein Ausdruck wurde vom Typ erwartet ('e,' c) reactInstance -> 'f ->' c -> Einheit Typ 'a ->' b -> 'c ist nicht kompatibel mit dem Typ (' e, 'c) reactInstance " – Drup

+0

Es gibt mehrere Dinge, die aussehen wie Fehler in die Datei, aber es ist schwer, sie zu lösen, ohne zu wissen, was die angebliche Semantik Ihrer Operationen ist. Die erste Sache, die zu mir springt, ist das "a." Im Updaterfeld, bist du sicher, dass du ein forall hier benutzen möchtest? Es scheint nicht sehr nützlich zu sein. – Drup

Antwort

2

Eine Typvariable '_a (der eigentliche Buchstabe spielt keine Rolle, das Entscheidende ist der Unterstrich) ist eine sogenannte schwache Typvariable. Dies ist eine Variable, die nicht verallgemeinert werden kann, d. H. Sie kann durch nur einen konkreten Typ ersetzt werden. Es ist wie ein veränderbarer Wert, aber im Bereich der Typen.

Ein mit einer schwachen Typvariablen '_a gekennzeichneter Typ ist nicht in einem Typ enthalten, der mit einer generischen Typvariablen bezeichnet wird. Außerdem kann es der Kompilierungseinheit nicht entkommen und sollte entweder versteckt oder konkretisiert werden.

Schwache Typvariablen werden erstellt, wenn ein Ausdruck kein reiner Wert ist (der syntaktisch definiert ist). Normalerweise ist es entweder eine Funktionsanwendung oder eine Abstraktion. Es ist normalerweise möglich, schwache Typenvariablen durch Ausführen einer sogenannten eta-Erweiterung zu entfernen, wenn Sie eine teilweise angewandte Funktion durch Aufzählung aller Funktionsargumente, d. H. updater = (fun props f i e -> mkUpdater props f i e), durch eine normale Funktionsanwendung ersetzen.

+0

danke für die tolle Erklärung! – Seneca