tutorial online funciones empresa descargar constructora company haskell

online - haskell pdf



ImplementaciĆ³n de la funciĆ³n nula. (3)

Tengo que aprender Haskell para la universidad y por eso estoy usando learnyouahaskell.com para el comienzo.
Siempre usé lenguajes imperativos, así que decidí practicar Haskell codificando mucho más de lo que lo haría para otros idiomas.
Comencé a implementar varias funciones para trabajar con listas como head , tail , init , ...
En algún momento busqué las implementaciones de estas funciones para compararlas con las mías y me topé con la función nula definida en List.lhs .

implementación nula:

-- | Test whether a list is empty. null :: [a] -> Bool null [] = True null (_:_) = False

mi implementación:

mNull :: [a] -> Bool mNull [] = True mNull _ = False

Sé que no hay preguntas estúpidas, incluso para preguntas tan simples :)
Entonces, mi pregunta es ¿por qué la implementación original usa (_:_) lugar de solo _ ?
¿Hay alguna ventaja en el uso de (_:_) o hay algún caso límite que no conozca?
Realmente no puedo imaginar ninguna ventaja porque _ atrapa todo.


No puedes simplemente cambiar las cláusulas con tu solución:

mNull'' :: [a] -> Bool mNull'' _ = False mNull'' [] = True

esto siempre dará como resultado False , incluso si pasa una lista vacía. Debido a que el tiempo de ejecución nunca considera la cláusula [] , inmediatamente ve _ coincide con cualquier cosa. (GHC le advertirá sobre este patrón superpuesto).

Por otra parte,

null'' :: [a] -> Bool null'' (_:_) = False null'' [] = True

sigue funcionando correctamente, porque (_:_) no coincide con el caso particular de una lista vacía.

Eso en sí mismo no da realmente una ventaja a las dos cláusulas explícitas. Sin embargo, en un código más complicado, escribir todas las opciones de exclusión mutua tiene un beneficio: si ha olvidado una opción, el compilador también puede advertirle sobre eso. Considerando que un _ puede y solo manejará cualquier caso no tratado por las cláusulas anteriores, incluso si eso no es realmente correcto.


Porque _ literalmente significa cualquier cosa aparte de patrones explícitamente especificados. Cuando especifica (_:_) significa cualquier cosa que pueda representarse como una lista que contenga al menos 1 elemento, sin preocuparse por qué o incluso cuántos elementos contiene realmente la lista. Dado que el caso con un patrón explícito para una lista vacía ya está presente, (_:_) podría ser reemplazado por _ .

Sin embargo, representarlo como (_:_) le brinda la flexibilidad de no pasar ni siquiera explícitamente el patrón de lista vacía. De hecho, esto funcionará:

-- | Test whether a list is empty. null :: [a] -> Bool null (_:_) = False null _ = True

Demo


Voy a añadir a lo que dijo alrededor de la izquierda. Esto no es realmente una preocupación potencial para el tipo de lista, pero en general, los tipos de datos a veces se modifican. Si tienes un mal concebido

data FavoriteFood = Pizza | SesameSpinachPancake | ChanaMasala

y luego aprenderá a gustar DrunkenNoodles y agregarlo a la lista, todas las funciones que coincidan con el patrón tendrán que expandirse. Si ha utilizado algún _ patrón, deberá buscarlo manualmente; El compilador no puede ayudarte. Si ha hecho coincidir cada cosa explícitamente, puede activar los -fwarn-incomplete-patterns y GHC le informará sobre cada punto que haya perdido.