2016-06-28 11 views
2

Ich arbeite durch die Definition Prompt und seine Bind Instanz beschrieben here und versuchte herauszufinden, wie dies in Purescript aussehen würde.Prompt Monad in Purescript

Ich verwende Purescript.Exists für den existentiellen Typ. Mein defintion ist dann:

data PromptAskF p r a 
    = PromptAskF (p a) (a -> Prompt p r) 

type PromptAsk p r = Exists (PromptAskF p r) 

data Prompt p r 
    = Ask (PromptAsk p r) 
    | Answer r 

instance bindPrompt :: Bind (Prompt p) where 
    bind (Answer x) k = k x 
    bind (Ask ask) k = ??? 

Ich stecke auf das Schreiben der Ask Fall in der Bind Instanz und insbesondere, ich bin sehr verwirrt über die Typen, wenn sie mit runExists arbeiten.

Wie soll ich diese Instanz schreiben?

Danke,

Michael

Antwort

1

so etwas sollte es tun:

data PromptAskF p r a 
    = PromptAskF (p a) (a -> Prompt p r) 

type PromptAsk p r = Exists (PromptAskF p r) 

mapPA 
    :: forall p r r' 
    . (forall a. (a -> Prompt p r) -> (a -> Prompt p r')) 
    -> PromptAsk p r 
    -> PromptAsk p r' 
mapPA f = runExists \(PromptAskF req cont) -> mkExists $ PromptAskF req (f cont) 

data Prompt p r 
    = Ask (PromptAsk p r) 
    | Answer r 

instance functorPrompt :: Functor (Prompt p) where 
    map f (Answer r) = Answer (f r) 
    map f (Ask ask) = Ask $ mapPA (map (map f)) ask 

instance applyPrompt :: Apply (Prompt p) where 
    apply = ap 

instance applicativePrompt :: Applicative (Prompt p) where 
    pure = Answer 

instance bindPrompt :: Bind (Prompt p) where 
    bind (Answer x) k = k x 
    bind (Ask ask) k = Ask $ mapPA (\cont ans -> cont ans >>= k) ask 

instance monadPrompt :: Monad (Prompt p) 

Die mapPA Funktion ist eine Bequemlichkeit, die PromptAskF Fortsetzung für die Aktualisierung ohne runExists/mkExists wiederholt zu haben.

+0

Hallo Gary, danke für deine Antwort. Das macht für mich Sinn, aber anscheinend nicht für den Typ-Checker! Ich erhalte den folgenden Fehler: 'Fehler gefunden: im Modul Haupt in Zeile 26, Spalte 1 - Zeile 30, Spalte 26 Eine Typvariable hat seinen Bereich entkommen. im Ausdruck (flip runExists) fragen in Wertdeklaration bindPrompt' –

+0

Ich habe gerade die Antwort aktualisiert, um die vollständige Implementierung zu enthalten, um sicherzustellen, dass es dieses Mal tatsächlich threechecks! Diese Fehlermeldung kann manchmal ziemlich schwierig sein, in diesem Fall war es wegen 'flip' 'runExists', aber selbst danach gab es etwas Seltsames (konnte das Lambda nicht in ein' wo' bringen, ohne dass es dazu kam). Wenn Sie es in 'runPA' verschieben, ist es ein wenig einfacher zu lesen, und wenn Sie die explizite Typ-Signatur für die Mapping-Funktion zur Verfügung stellen, vermeiden Sie andere potenzielle Skolem-Escape-Probleme. –

+0

Super! Danke, dass Sie sich die Zeit genommen haben, um zu aktualisieren. Das ist mir jetzt dank der expliziten Rang-n-Typen tatsächlich klarer als die Haskell-Implementierung. –