2016-09-10 14 views
5

Ich versuche, eine kostenlose Monad-Bibliothek in Ocaml, Control.Monad.Free von Haskell zu schreiben, aber ich bin an einem Punkt fest, in der Implementierung von hoistFree.Widen Typen in Ocaml

hoistFree :: Functor g => (forall a. f a -> g a) -> Free f b -> Free g b 
hoistFree _ (Pure a) = Pure a 
hoistFree f (Free as) = Free (hoistFree f <$> f as) 

Hier ist mein Versuch einer Übersetzung.

Leider bekomme ich einen Fehler, der mir sagt, dass ich die Art von g nicht richtig verbreite.

Error: This definition has type ('b m t -> 'b m t) -> 'b m -> 'b m 
     which is less general than 'a. ('a t -> 'a t) -> 'b m -> 'b m 

Alles funktioniert gut, wenn ich nicht die Funktion Typanmerkung einfügen, aber dann als die Fehlermeldung sagt, ich habe nicht den allgemeinen Typen für f. Wo ist das Problem? Wie kann ich die Art von f erweitern?

Antwort

3

ich mit Ocaml nicht sehr vertraut bin, aber ich glaube, dass

let rec hoistfree : 'b.('b t -> 'b t) -> 'a m -> 'a m = 

analysiert wird als

let rec hoistfree : 'b. (('b t -> 'b t) -> 'a m -> 'a m) = 

statt

let rec hoistfree : ('b. ('b t -> 'b t)) -> 'a m -> 'a m = 

Erstere ein grundlegender polymorpher Typ ist, Letzteres ist ein Rank2-Typ, der vom Typsystem mehr Unterstützung benötigt als Hindley-Milner.

IIRC, um Letzteres zu erreichen, müssen Sie einen benutzerdefinierten Wrapperdatentyp definieren. Zum Beispiel:

type poly = { polyf: 'a . 'a -> 'a } ;; 

let foo (x: poly): int = x.polyf 4;; 
let bar: poly = { polyf = fun x -> x } ;; 

let _ = print_string ("hello "^string_of_int (foo bar));; 
+0

danke für die Antwort. Ich versuche immer noch, deine Idee in meiner speziellen Umgebung umzusetzen. – stackman