2012-03-30 12 views
5

Quiero hacer que mi transformador de mónada sea una instancia de MonadError si la mónada transformada es una instancia. Básicamente quiero que mi transformador de comportarse como los transformadores incorporados hacen, por ejemplo, hay una instancia MonadError para StateT:Hacer un transformador de mónada personalizado una instancia de MonadError

MonadError e m => MonadError e (StateT s m) 

Intenté hacer esto:

instance MonadError e m => MonadError e (MyMonadT m) 

Pero GHC comenzó a quejarse de indecidible instancias, al parecer, la biblioteca MTL solo habilita instancias indecidibles, pero ¿hay alguna forma de evitar eso? ¿O está bien en este caso y no causará ningún problema?

Respuesta

8

Esto está básicamente bien. UndecidableInstances no es tan aterrador; todo lo que significa es que el compilador podría, en lugar de encontrar una instancia, entrar en un ciclo infinito. Que suena como bastante malo, hasta que te das cuenta de que GHC en realidad tiene un límite en el número de pasos que tomará encontrar una instancia; nada saldrá mal a menos que escriba una mala instancia, y los mensajes de error que obtenga generalmente harán que sea muy obvio lo que salió mal. Sin duda, es mucho menos aterrador que cosas como OverlappingInstances (o peor, IncoherentInstances).

La razón por la que se queja es porque MonadError tiene una dependencia funcional de m a e. Eso significa que la elección de m determina qué debe ser e; es decir, cada m está asociado con solo un e. El control de esto (la Condición de cobertura) es conservador, por lo que es fácil tener problemas como este, donde intenta y "recurse a un nivel bajo" para especificar e.

Enumerará todas las instancias que buscó para tratar de encontrar la que está buscando, por lo que verá un montón de líneas repetitivas. Pero, por lo general, ni siquiera tendrás problemas como este en primer lugar.

Cuestiones relacionadas