haskell - Patrones no exhaustivos en función
pattern-matching non-exhaustive-patterns (2)
Esta pregunta ya tiene una respuesta aquí:
Tengo un problema con este código, debería contar la subcadena más larga de la misma letra en una cadena, pero hay un error:
*** Exception: test.hs:(15,0)-(21,17):
Non-exhaustive patterns in function countLongest''
Sé que es un problema de tipos incorrectos, pero no sé dónde está el error, ni cómo encontrarlo o depurarlo.
countLongest :: (Eq a) => [a] -> Int
countLongest'' :: (Eq a) => Int -> Int -> [a] -> Int
countLongest a = countLongest'' 0 0 a
countLongest'' n max (y:x:ys)
| y == x = countLongest'' (n+1) max (x:ys)
| n > max = countLongest'' 0 (n) (x:ys)
| otherwise = countLongest'' 0 (max) (x:ys)
countLongest'' n max []
| n > max = n
| otherwise = max
El problema es que debe coincidir si hay 1 elemento en la recursión, por ejemplo:
countLongest'' n max (y:ys)
Porque el primero coincide si quedan 2 o más elementos y el último solo coincide si no queda ningún elemento.
Parece que te estás perdiendo el caso donde hay una lista de un elemento:
countLongest'' n max (y:ys)
| ... etc. ...
| otherwise = ....
Aquí hay un ejemplo artificial similar al tuyo:
f [] = 3 -- matches an empty list
f (a:b:bs) = 4 -- matches a list with at least two elements
Ejemplos:
Prelude> :load myfile.hs
[1 of 1] Compiling Main ( myfile.hs, interpreted )
Ok, modules loaded: Main.
*Main> f [3]
*** Exception: myfile.hs:(3,0)-(4,13): Non-exhaustive patterns in function f
*Main> f []
3
*Main> f [1,2,3,4,5]
4
*Main>
Entonces, tiene éxito con 0 y 2 elementos en la lista, pero falla cuando hay exactamente un elemento.
Tenga en cuenta que este comportamiento no es exclusivo de las listas. Aquí hay un ejemplo usando Maybe
:
g :: Maybe x -> x
g (Just x) = x
Ejemplos:
*Main> g (Just 4)
4
*Main> g Nothing
*** Exception: myfile.hs:6:0-13: Non-exhaustive patterns in function g
Esto sucedió porque hay dos constructores para Maybe
, Just <something>
y Nothing
. No proporcionamos un caso para Nothing
, así que cuando pasamos eso a g
, ¡no funcionó!
Echa un vistazo a esta pregunta y sus respuestas para obtener información sobre cómo obtener un poco de ayuda del compilador. Seguí el consejo de la primera respuesta, y cuando cargué mis ejemplos, esto es lo que sucedió:
prompt$ ghci -fwarn-incomplete-patterns
Prelude> :load myfile.hs
[1 of 1] Compiling Main ( myfile.hs, interpreted )
myfile.hs:3:0:
Warning: Pattern match(es) are non-exhaustive
In the definition of `f'': Patterns not matched: [_]
myfile.hs:6:0:
Warning: Pattern match(es) are non-exhaustive
In the definition of `g'': Patterns not matched: Nothing
Ok, modules loaded: Main.
¡Guay! El compilador es bastante inteligente!