Geben Sie Fehler beim Versuch, die (>> =) Funktion zu implementieren, um einen benutzerdefinierten Monade Transformator zu schaffen

StackOverflow https://stackoverflow.com/questions/2661895

Frage

Ich versuche, einen Monade Transformator für ein zukünftiges Projekt zu erstellen, aber leider meine Umsetzung der Monad typeclasse der (>> =) Funktion funktioniert nicht.

Zunächst einmal ist hier die Umsetzung der zugrunde liegenden Monade:

newtype Runtime a = R { 
  unR :: State EInfo a
} deriving (Monad)

Hier wird die Umsetzung der Monade typeclasse erfolgt automatisch durch GHC (die GeneralizedNewtypeDeriving Sprache Pragma verwenden). Der Monade Transformator ist definiert als so:

newtype RuntimeT m a = RuntimeT {
  runRuntimeT :: m (Runtime a)
} 

Das Problem kommt von der Art, wie ich instanziieren die (>> =) Funktion der Monade typeclasse:

instance (Monad m) => Monad (RuntimeT m) where
    return a = RuntimeT $ (return . return) a
    x >>= f =  runRuntimeT x >>= id >>= f

So wie ich es sehe, der erste >>= läuft in der zugrunde liegenden m Monade. Somit kehrt runRuntimeT x >>= einen Wert vom Typ Runtime a (rechts?). Dann wird der folgende Code, id >>= sollte einen Wert vom Typ a zurückzukehren. Dieser Wert wird die Weitergabe an die Funktion f vom Typ f :: (Monad m) => a -> RuntimeT m b.

Und hier kommt die Art Problem: die Typ der f Funktion nicht den durch die (>> =) Funktion erforderlich Typen entspricht. Jow kann ich diese kohärent machen? Ich kann sehen, warum dies nicht funktioniert, aber ich kann es nicht schaffen es in etwas functionnal zu machen.

Edit: Die Fehlermeldung:

Core.hs:34:4:
    Occurs check: cannot construct the infinite type: m = RuntimeT m
    When generalising the type(s) for `>>='
    In the instance declaration for `Monad (RuntimeT m)'
Failed, modules loaded: none.

Vielen Dank für Ihre Hilfe, und zögern Sie keine Fehler in meiner Nachricht zu korrigieren,
Charlie P.

War es hilfreich?

Lösung

Um zu folgen, was Reid Barton sagte über StateT - hier, wie Sie RuntimeT mit StateT definieren würde. Die Runtime Monade kann dann trivialerweise mit der Identität Monade definiert werden.

newtype RuntimeT m a = R { 
  unR :: StateT EInfo m a
}

type Runtime = RuntimeT Identity

instance Monad m => Monad (RuntimeT m) where
    return = R . return

    (R m) >>= f = R (m >>= unR . f)

Andere Tipps

Die übliche StateT s m Monade sendet a zu s -> m (a, s) aber Sie arbeiten mit m (s -> (a, s)) statt. Ich glaube nicht, Letztere bildet eine Monade für allgemeine s. Sind Sie sicher, dass Sie nicht nur StateT verwenden?


Hier ist, warum ich glaube nicht, a ? m (s -> (a, s)) ist eine Monade: Um Schreib >>= Ich brauche eine Funktion, die Argumente der Typen

nimmt
m (s -> (a, s))
a -> m (s -> (b, s))

und gibt einen Wert vom Typ

m (s -> (b, s))

Die „Effekte“ (das heißt fmap (const ())) des Ergebnisses müssen mit denen des ersten Arguments, da wir keine Möglichkeit haben, eine a zu bekommen, um das zweite Argument zu übergeben. Da m nur auf der Außenseite des Ergebnistypen angezeigt wird, können wir dann nicht das zweite Argument an für alles verwenden alles gibt es keine Möglichkeit, um von der m führt es los zu werden.

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