Frage

Weiter Quest Sinn ContT und Freunde zu machen. Bitte beachten Sie den (absurd, aber zur Veranschaulichung) Code unten:

v :: IO (Either String [String])
v = return $ Left "Error message"

doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
    x <- liftIO $ v
    x2 <- either (k . Left) return x
    when True $ k (Left "Error message 2")
    -- k (Left "Error message 3")
    return $ Right () -- success

Dieser Code nicht kompiliert. Wenn jedoch der die when mit dem kommentierten k Anruf darunter ersetzen, es kompiliert. Was ist los?

Alternativ kann, wenn ich die x2 Zeile aus kommentieren, es kompiliert auch. ???

Offensichtlich ist dies eine destillierte Version des Original-Code und so alle Elemente dienen einem Zweck. Schätzen erklärend Hilfe auf, was los ist und wie man es beheben. Danke.

War es hilfreich?

Lösung

Das Problem hat mit der Art des when und either, nicht etwas Besonderes zu ContT zu tun:

when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c

Das zweite Argument muß vom Typ m () für einige Monade m sein. Die when Zeile des Codes so wie so geändert werden:

when True $ k (Left "Error message 2") >> return ()

Kompilieren Sie den Code zu machen. Dies ist wahrscheinlich nicht das, was Sie tun wollen, aber es gibt uns einen Hinweis darüber, was könnte falsch sein. k den Typ abgeleitet wurde etwas ungenießbar when sein

Jetzt für die either Unterschrift: bemerken, dass die beiden Argumente either Funktionen, die Ergebnisse des gleichen Typs zu produzieren sein. Die Art der return hier wird durch die Art der x bestimmt, die durch die explizite Unterschrift auf v fixiert wiederum ist. Somit muss das (k . Left) Bit denselben Typ haben; Dies wiederum legt die Art der k bei (GHC bestimmt)

k :: Either String () -> ContT (Either String ()) IO [String]

Dies ist unvereinbar mit when Erwartungen.

Wenn Sie die x2 Zeile aus kommentieren, aber seine Wirkung auf die Ansicht der Typprüfer des Codes entfernt wird, so k wird nicht mehr in eine unbequeme Art gezwungen und ist frei, um die Art zu übernehmen

k :: Either [Char] () -> ContT (Either [Char] ()) IO ()

, das ist in when Buch in Ordnung. Somit stellt der Code.

Als abschließende Bemerkung, benutzte ich GHCi der Stützpunkte Einrichtung die genauen Arten von k unter den beiden Szenarien zu erhalten - ich lange nicht Experte genug bin, um sie mit der Hand zu schreiben, und in keiner Weise von ihrer Richtigkeit gewährleistet sein. :-) Verwenden Sie :break ModuleName line-number column-number, um es auszuprobieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top