modules - ¿Por qué este código Haskell produce el error de "tipo infinito"?
syntax record haskell (4)
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 sucede cuando dejo que ghc adivine el tipo de intercalado:
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''
Eso 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.
Soy nuevo en Haskell y enfrento un error de "no se puede construir un tipo infinito" que no puedo entender.
De hecho, más allá de eso, no he podido encontrar una buena explicación de lo que significa este error, así que si pudieras ir más allá de mi pregunta básica y explicar el error de "tipo infinito", realmente lo agradecería.
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 al 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í hay algunos que corrigieron el código y una guía general para tratar el error de "tipo infinito" en Haskell:
Código corregido
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) = x ++ s:intersperse s xs
Cuál fue el problema?
Mi firma tipo indica que el segundo parámetro para intercalar es una lista 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.
Pauta para tratar el error de "tipo infinito":
La mayoría de las veces, cuando obtiene este error, ha olvidado los tipos de las diversas variables con las que está tratando, y ha intentado utilizar una variable como si fuera de algún otro tipo. Mire cuidadosamente qué tipo es todo versus cómo lo está usando, y esto generalmente descubrirá el problema.
El problema está en la última cláusula, donde tratas xey como elementos, mientras que son listas. Esto funcionará:
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs
El error de tipo infinito ocurre porque el operador: tiene un tipo a -> [a] -> [a], mientras que 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
Puedo estar equivocado, pero parece que estás tratando de resolver un problema más difícil. Tu versión de intersperse
no solo intercala el valor con el arreglo, sino que también lo aplana un nivel.
El módulo de List
en Haskell en realidad proporciona una función intercalada. Pone en el valor dado 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"]
Asumo que esto es lo que quieres hacer porque es lo que mi profesor quería que hiciéramos cuando estaba aprendiendo a Haskell. Podría, por supuesto, estar totalmente fuera.
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 alguna tupla parametrizada como parámetro formal. Todo funciona correctamente eliminando la definición de tipo de la función, que contenía variables de tipo.
Todavía no puedo entender cómo solucionarlo y mantener la definición del tipo de función.