Error de functor al usar un dato dentro de un dato: "no se puede construir el tipo infinito"

Mientras aprendía más sobre el sistema de tipos de Haskell, encontré este problema con el juguete. Cuando compilo el siguiente código:

data SingleData a = SingleData a Int String -- etc.
data DataFail a = DataFail [SingleData a]
instance Functor DataFail where
    fmap f (DataFail xs) = DataFail (map f xs)

Recibo el temido mensaje "Ocurre verificación: no se puede construir el tipo infinito: b = SingleData b" en la definición de fmap. Curiosamente, la misma definición de fmap funcionará si está fuera de la declaración de instancia:

fmapWorks f (DataFail xs) = DataFail (map f xs)

Aún más extraño, la implementación de Monoid se compila y funciona bien:

instance Monoid (DataFail a) where
    mempty = DataFail []
    mappend (DataFail xs) (DataFail ys) = DataFail (xs ++ ys)

Creo que esto es de alguna manera el resultado de usar SingleData dentro de DataFail, porque esto también funciona bien:

data DataSuccess a = DataSuccess [a]
instance Functor DataSuccess where
    fmap f (DataSuccess xs) = DataSuccess (map f xs)

¿Por qué Haskell se queja de la función fmap de DataFail y qué puedo hacer para solucionarlo?

preguntado el 20 de septiembre de 11 a las 06:09

Si miras el tipo de fmapWorks Verás que no es del tipo necesario para fmap. -

1 Respuestas

El error "Ocurre comprobación" no es y eso temido ...

El problema es la función proporcionada a fmap. Prueba esto:

instance Functor SingleData where
  fmap f (SingleData a i s) = SingleData (f a) i s

instance Functor DataFail where
  fmap f (DataFail sds) = DataFail $ map (fmap f) sds

Entonces, el error real es su uso de map: el tipo no coincide. Functor espera que sea de tipo a -> b, pero la forma en que lo estás usando es de tipo SingleData a -> SingleData b; el extra Functor instancia para SingleData te permite usar fmap para aplicar la función directamente al valor dentro de ella.

Respondido el 20 de Septiembre de 11 a las 10:09

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.