2011-04-29 10 views
5

Estoy usando GHCi (versión 6.12.3) para jugar un poco con Haskell. Recientemente leí acerca de funtores y funtores aplicativos pensé que si no podías hacer algo similar al <*> de los funtores aplicativos se implementaría solo con las primitivas del functor. Después de pensarlo se me ocurrió fmap fmap que tendría un (casi) tipo ideal deHaskell - fmap fmap no funciona

Functor f => f (a -> b) -> f (f a -> f b) o más genéricamente

(Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b)

Probé

let q = fmap fmap 

Tengo el siguiente error

<interactive>:1:8: 
    Ambiguous type variable `f1' in the constraint: 
     `Functor f1' arising from a use of `fmap' at <interactive>:1:8-16 
    Probable fix: add a type signature that fixes these type variable(s) 

<interactive>:1:13: 
    Ambiguous type variable `f' in the constraint: 
     `Functor f' arising from a use of `fmap' at <interactive>:1:13-16 
    Probable fix: add a type signature that fixes these type variable(s) 

Escribir la firma del tipo anterior como se sugirió no ayudó. Lo más loco es cuando escribí :t fmap fmap Obtuve un tipo equivalente al anterior.

¿Qué estoy haciendo mal? ¿Por qué fmap fmap da un error de tipo aunque GHCi encuentra un tipo para él?

Respuesta

7

Parece que se está ejecutando en el monomorphism restriction.

Si prueba su ejemplo en GHCi con -XNoMonomorphismRestriction obtendrá el resultado esperado.

También puede subvertir esto escribiendo let f x = fmap fmap $ x. La restricción de monomorfismo solo se aplica a las definiciones de nivel superior que se parecen a los valores, es decir, f = something, por lo que la introducción de un argumento explícito hace que no se aplique más. Tampoco se aplicaría si no estuviera en el nivel superior (por ejemplo, en una cláusula where). Para más detalles, mira el enlace.

+1

Parece ser la restricción del monomofismo porque tu alma funciona. Gracias. Pero, ¿por qué no funcionó cuando especifiqué el tipo? – Mafi

1

No puedo comentar en todas partes todavía así que voy a publicar una respuesta. Como se mencionó anteriormente, el error que está recibiendo se debe a la restricción de monomorfismo. La corrección de la firma de tipo para cualquiera de los dos dados en la pregunta original hace que ghci sea feliz como esperabas, ¿tal vez acabas de obtener la sintaxis un poco mal?

 
Prelude> let q :: (Functor f) => f (a -> b) -> f (f a -> f b); q = fmap fmap 
Prelude> :t q 
q :: (Functor f) => f (a -> b) -> f (f a -> f b) 

Prelude> let q :: (Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b); q = fmap fmap 
Prelude> :t q 
q :: (Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b) 
+0

Sí, acabo de entender la sintaxis. Gracias – Mafi