Tipo di errore durante il tentativo di implementare la funzione (>> =) al fine di creare un trasformatore monade personalizzato

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

Domanda

Sto cercando di creare un trasformatore monade per un progetto futuro, ma purtroppo, il mio attuazione di Monade typeclasse (>> =) funzione non è attiva.

Prima di tutto, qui è l'implementazione del monade sottostante:

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

Qui, l'attuazione della Monade typeclasse viene fatto automaticamente dal GHC (utilizzando il linguaggio pragma GeneralizedNewtypeDeriving). La monade trasformatore è definito come:

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

Il problema deriva dal modo in cui ho instanciate la funzione (>> =) del typeclasse Monade:

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

Il mio modo di vedere, le prime corse >>= nella monade m sottostante. Così, runRuntimeT x >>= restituisce un valore di tipo Runtime a (giusto?). Poi, il codice seguente, id >>=, dovrebbe restituire un valore di tipo a. Questo valore è il trasmesso alla funzione f di tipo f :: (Monad m) => a -> RuntimeT m b.

E qui viene il problema Tipo: il tipo di funzione di f non corrisponde al tipo richiesto dalla funzione (>> =). Jow posso fare questo coerente? Posso capire perché questo non funziona, ma non riesco a trasformarlo in qualcosa di functionnal.

Modifica: Il messaggio di errore:

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.

Grazie per aiuto, e non esitate a correggere eventuali difetti nel mio messaggio,
Charlie P.

È stato utile?

Soluzione

Per riallacciarmi a ciò che ha detto Reid Barton su StateT - ecco come si potrebbe definire RuntimeT utilizzando StateT. La monade Runtime può essere banalmente definita utilizzando la monade identità.

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)

Altri suggerimenti

Il solito StateT s m monade manda a a s -> m (a, s) ma si sta lavorando con m (s -> (a, s)) invece. Non credo che queste ultime forme una monade per s generale. Sei sicuro che non vuoi solo usare StateT?


Ecco il motivo per cui non credo am (s -> (a, s)) è una monade: Per >>= scrivere ho bisogno di una funzione che prende argomenti di tipi

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

e restituisce un valore di tipo

m (s -> (b, s))

Gli "effetti" (cioè fmap (const ())) del risultato deve essere quelle del primo argomento, poiché abbiamo modo per ottenere un a per passare al secondo argomento. Dal momento che appare m solo sulla parte esterna del tipo di risultato, abbiamo poi non si può utilizzare il secondo argomento per niente-non ci sarà alcun modo per sbarazzarsi del m introduce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top