2009-04-27 8 views
59

Soy nuevo en Haskell y estoy frente a un error de "no se puede construir el tipo infinito" que no puedo entender.¿Por qué este código Haskell produce el error de "tipo infinito"?

De hecho, más allá de eso, no he podido encontrar una buena explicación de lo que este error significa, así que si pudieras ir más allá de mi pregunta básica y explicar el error del "tipo infinito", realmente apreciaría eso.

Aquí está el código:

intersperse :: a -> [[a]] -> [a] 

-- intersperse '*' ["foo","bar","baz","quux"] 
-- should produce the following: 
-- "foo*bar*baz*quux" 

-- intersperse -99 [ [1,2,3],[4,5,6],[7,8,9]] 
-- should produce the following: 
-- [1,2,3,-99,4,5,6,-99,7,8,9] 

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:y:xs) = x:s:y:intersperse s xs 

Y aquí está el error de tratar de cargarlo en el intérprete:

Prelude> :load ./chapter.3.ending.real.world.haskell.exercises.hs 
[1 of 1] Compiling Main (chapter.3.ending.real.world.haskell.exercises.hs, interpreted) 

chapter.3.ending.real.world.haskell.exercises.hs:147:0: 
Occurs check: cannot construct the infinite type: a = [a] 
When generalising the type(s) for `intersperse' 
Failed, modules loaded: none. 

Gracias.

-

Aquí es un poco de corregir el código y una guía general para tratar con el error "infinita" en Haskell:

código corregido

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:xs) = x ++ s:intersperse s xs 

Lo que el el problema era:

Mi estado de firma de tipo s que el segundo parámetro para intercalar es una lista de de listas. Por lo tanto, cuando el patrón coincide con "s (x: y: xs)", xey se convirtieron en listas. Y sin embargo, estaba tratando x e y como elementos, no como listas.

Guía para hacer frente a la "infinita de tipo" error:

mayoría de las veces, cuando recibe este error, se han olvidado de los tipos de las diversas variables que está tratando, y usted han intentado usar una variable como si fuera de algún otro tipo de lo que es. Mire cuidadosamente qué tipo es todo versus cómo lo está usando, y esto generalmente descubrirá el problema.

+1

Otro buen consejo: declare los tipos explícitamente. Esto le da algo al compilador para contrastar. –

+1

Así que esto resuelve el problema, pero ¿por qué el compilador dice "No se puede construir el tipo infinito?". Qué significa eso? Si el problema es que está tratando de realizar operaciones en tipos que no son compatibles con esas operaciones, ¿por qué el compilador no dice algo así? – freedrull

+9

+1 para la estructura de la pregunta (pregunta - corregida - el problema fue - guía) – Dacav

Respuesta

27

El problema está en la última cláusula, donde trata xey como elementos, mientras que son listas. Esto funcionará:

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs 

se produce el error de tipo infinita porque el: operador tiene el tipo a -> [a] -> [a], mientras que usted lo trata como [a] -> a -> [a] , lo que significa que [a] debe identificarse con a, lo que significaría que a es una lista infinitamente anidada. Eso no está permitido (y no es lo que quieres decir, de todos modos).

Editar: También hay otro error en el código anterior. Debería ser:

intersperse _ [] = [] 
intersperse _ [x] = x 
intersperse s (x:xs) = x ++ [s] ++ intersperse s xs 
+0

Gracias. Calculé que ambos salieron y luego volví aquí y vi tu respuesta, que fue una excelente verificación para mí. También arregló mi error mejor que yo. Mi error fue que se estaba saltando un separador entre y y xs. Para solucionarlo, introduje otro nivel de coincidencia de patrones, como este: intersperse s (x: y: []) = x ++ s: y intersperse s (x: y: xs) = intersperse s [x, y] ++ s: intersperse s xs Pero parece que corrigió mi error sin la necesidad de ese nivel adicional. –

+1

Aquí está la lección que aprendo: "Cuando enfrenta un error de 'tipo infinito', probablemente esté olvidando los tipos con los que está tratando y, por lo tanto, está haciendo algo que no tenía intención de hacer. Mire cuidadosamente de qué tipo es cada uno de sus las variables son, y eso generalmente descubrirá el problema ". ¿Hay algo que agregar o cambiar en eso? –

+0

Eso es ciertamente correcto, y no cambiaría nada en eso.Los tipos infinitos no están permitidos, y por lo tanto un error de tipo infinito significa que en alguna parte una función recibe un argumento con un tipo incorrecto. Buena suerte con RWH :) – Stephan202

2

Puedo estar equivocado, pero parece que estás tratando de resolver un problema más difícil. Su versión de intersperse no solo intercala el valor con la matriz, sino que también lo allana un nivel.

El módulo List en Haskell realmente proporciona una función intercalada. Introduce el valor entre cada elemento en la lista.Por ejemplo:

intersperse 11 [1, 3, 5, 7, 9] = [1, 11, 3, 11, 5, 11, 7, 11, 9] 
intersperse "*" ["foo","bar","baz","quux"] = ["foo", "*", "bar", "*", "baz", "*", "quux"] 

Estoy asumiendo que esto es lo que quiere hacer porque es lo que mi profesor quería que nosotros hacemos cuando estaba aprendiendo Haskell. Podría, por supuesto, estar totalmente fuera.

+0

Gracias por el comentario. En este caso, sin embargo, quiero aplanarlo un nivel, porque estoy haciendo el ejercicio 7 desde el final del capítulo 3 de "Real World Haskell". –

+0

Gotcha. Si tuviera el libro, lo habría revisado antes de escribirlo. Por desgracia, todo lo que pude hacer fue adivinar. Me alegra que lo hayas ordenado de todos modos. :-) –

+4

El contenido del libro está disponible de forma gratuita en línea: http://book.realworldhaskell.org/ – Stephan202

0

También encontré this que explica el significado del error.

Cada vez que el intérprete/compilador me da este error es porque estoy usando una tupla tipo-parametrizada como parámetro formal. Todo funciona correctamente al eliminando la definición de tipo de la función, que contenía variables de tipo.

Todavía no puedo encontrar la manera de solucionarlo y mantener la definición del tipo de función.

3

A menudo, agregar una definición explícita de tipo puede hacer que el mensaje de error de tipo del compilador tenga más sentido. Pero en este caso, la escritura explícita empeora el mensaje de error del compilador.

Mira lo que pasa cuando dejo GHC adivinar el tipo de intersperse:

Occurs check: cannot construct the infinite type: a = [a] 
    Expected type: [a] -> [[a]] -> [[a]] 
    Inferred type: [a] -> [[a]] -> [a] 
In the second argument of `(:)', namely `intersperse s xs' 
In the second argument of `(:)', namely `y : intersperse s xs' 

que apunta claramente hacia el error en el código. Usando esta técnica no tienes que mirar todo y pensar mucho sobre los tipos, como otros han sugerido hacer.

Cuestiones relacionadas