Estoy tratando de crear mi propio tipo de datos, que formará parte de la clase Monad, pero
newtype Container a = Container a deriving Monad
me da este error:
* Can't make a derived instance of `Monad Container'
(even with cunning GeneralizedNewtypeDeriving):
cannot eta-reduce the representation type enough
* In the newtype declaration for `Container'
|
30 | newtype Container a = Container a deriving Monad
Funciona bien para otras clases (Mostrar, por ejemplo), pero no para Monad, entonces, ¿cómo puedo convencer a ghci de que instale mi clase Container to Monad?
Gracias

ano es una instancia de mónada, por lo tanto, no tiene mucho sentido. Si, por ejemplo, lo usanewtype Container a = Container [a] deriving (Functor, Applicative, Monad), funcionará, ya que[]es una instancia deMonad.GenerlizedNewtypeDerivinges específicamente para "levantar" las instancias del tipo envuelto al nuevo tipo. La pregunta de cómo (o si) uno puede derivar automáticamente unaMonadinstancia paraContainertodavía es interesante. (El hecho quebasedefine laMonadinstancia paraIdentityexplícito sugiere que no puede)Monadno es una de las clases de tipos que el estándar Haskell pone a disposición para ser derivadas automáticamente (Showes, junto con algunas otras básicas). Sin embargo, creo que GHC puede hacerlo con las extensiones correctas.GeneralizedNewtypeDerivingestá habilitado, y una pregunta es por qué todavía no funciona.Respuestas:
Solo un conjunto fijo de clases estándar admite la derivación de fábrica:
En particular
Monadno pertenece a esa lista, ni a la extendida.Hay más extensiones que generalizan derivando a clases arbitrarias, pero no pueden ser 100% automatizadas. Alguien en algún lugar tiene que especificar cómo se debe hacer esa derivación; Dependiendo de la clase, se puede requerir que el usuario cargue con la carga porque hay información que fundamentalmente no se puede inferir.
En su caso, el nuevo tipo
Containeres representacionalmente equivalente a laIdentitymónada en la biblioteca estándar, por lo que puede usarDerivingVia:Solo hay una instancia sensata en esta situación muy particular, pero la mayoría de las veces no es fácil saber cuál debería ser la instancia, incluso si solo hay una.
fuente
FunctoryApplicative, pero luego comparar el tipo deContainer 3 >>= (+1)conIdentity 3 >>= (+1). No sé si eso está relacionadoDerivingViao no.Container 3 >>= (+ 1) :: Num (Container b) => Container byIdentity 3 >>= (+ 1) :: Num b => Identity b. No estoy seguro de por quéContainer b, en lugar deb, tiene laNumrestricción.)(+ 1) :: Num c => c -> ccomo flecha de Kleisli(+ 1) :: a -> Container bnecesitas unificarc ~ Container b. Pero no estoy seguro de cuál es su punto de partida.Identityque no se defineContainer, segúnIdentity 3 >>= (+1)evalúaIdentity 4.instance Num a => Num (Identity a)definido.