Tipo de error al intentar implementar la función (>> =) con el fin de crear un transformador mónada personalizada

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

Pregunta

Estoy intentando crear un transformador mónada para un proyecto futuro, pero por desgracia, mi implementación de la mónada de typeclasse (>> =) función no funciona.

En primer lugar, aquí es la implementación de la mónada subyacente:

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

A continuación, la aplicación de la Mónada typeclasse se realiza automáticamente por GHC (utilizando el lenguaje de Pragma GeneralizedNewtypeDeriving). La mónada transformador se define como así:

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

El problema proviene de la forma en que la función instanciate (>> =) de la typeclasse Mónada:

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

A mi modo de ver, las primeras carreras >>= en la mónada m subyacente. Por lo tanto, runRuntimeT x >>= devuelve un valor de tipo Runtime a (¿verdad?). A continuación, el código siguiente, id >>=, debería devolver un valor de tipo a. Este valor es la transmite a la función f de tipo f :: (Monad m) => a -> RuntimeT m b.

Y aquí viene el problema tipo: Tipo de la función f no coincide con el tipo requerido por la función (>> =). Jow puedo hacer que esta coherente? Puedo ver por qué esto no funciona, pero no puedo lograr convertirlo en algo functionnal.

Edit: El mensaje de error:

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.

Gracias por su ayuda, y no dude en corregir cualquier defecto en mi mensaje,
Charlie P.

¿Fue útil?

Solución

Para una continuación de lo que dijo Reid Barton sobre StateT - aquí es cómo definiría RuntimeT usando StateT. La mónada Runtime puede entonces ser trivialmente define utilizando la mónada identidad.

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)

Otros consejos

La mónada StateT s m habitual envía a a s -> m (a, s) pero están trabajando con m (s -> (a, s)) lugar. No creo que este último forma una mónada para s general. ¿Seguro que no sólo quiere utilizar StateT?


He aquí por qué no creo a ? m (s -> (a, s)) es una mónada: Para >>= escritura necesito una función que toma argumentos de tipos

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

y devuelve un valor de tipo

m (s -> (b, s))

Los "efectos" (es decir fmap (const ())) del resultado debe ser las del primer argumento, ya que no tenemos manera de obtener una a para pasar al segundo argumento. Desde m sólo aparece en la parte exterior del tipo de resultado, entonces no podemos usar el segundo argumento para nada en absoluto, no habrá manera de deshacerse de la m introduce.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top