Estoy trabajando en Aprenda You A Haskell para familiarizarse con los conceptos básicos de Haskell. Me siento muy cómodo tanto con la programación funcional como con la coincidencia de patrones, pero esta última más que con la forma en que lo hace Mathematica.Uso de patrones para encontrar el enésimo elemento
En el mismo espíritu que la aplicación ingenua de head
en el capítulo 4.1, que procedieron con una aplicación ingenua de last
como:
last1 :: [a] -> a
last1 (_:x:[]) = x
Sin embargo, llamando last1 [1,2,3,4]
dio un error Exception: ... Non-exhaustive patterns in function last1
. Entiendo que este error implica que el patrón especificado no cubre todas las entradas posibles y, por lo general, es necesario un patrón global (que no he proporcionado). Sin embargo, no estoy exactamente seguro de por qué recibo este error para mi entrada.
Pregunta 1: Mi comprensión (de mi enfoque incorrecto) es que el primer elemento es capturado por _
y el resto se asignan a x
, que no es exactamente lo que había previsto. Sin embargo, ¿no debería dar un error de tipo, porque he especificado [a] -> a
, pero x
ahora es una lista?
Tenga en cuenta que esto es no acerca de cómo escribir un last
función de trabajo - Sé que puedo escribir como (entre otras posibilidades)
last2 :: [a] -> a
last2 [x] = x
last2 (_:x) = last2 x
Pregunta 2: A lo largo del mismo tema de una mejor Entender la coincidencia de patrones en Haskell, ¿cómo puedo usar la coincidencia de patrones para elegir el último elemento o, más en general, el elemento n
de una lista determinada, por ejemplo, [1..10]
?
This answer sugiere que puede enlazar el último elemento utilizando coincidencia de patrones con la extensión ViewPatterns
, pero parece extraño que no hay un patrón similar "simple" como por head
En Mathematica, que sería probablemente escribir como:
Range[10] /. {Repeated[_, {5}], x_, ___} :> x
(* 6 *)
de seleccionar el sexto elemento y
Range[10] /. {___, x_} :> x
(* 10 *)
para seleccionar el último elemento de una lista no vacía.
Me disculpo si esto se trata más adelante en el texto, pero trato de relacionar cada tema y concepto a medida que los encuentro, a cómo se maneja en otros idiomas que conozco para que pueda apreciar las diferencias y similitudes.
¡Gracias por la explicación! Esto deja muy claro por qué no estaba funcionando. ¿Hay algún patrón para unir múltiples elementos? Por ejemplo, en la línea '{___, x_}' en mi ejemplo de Mathematica (al final), '___' implica "cero o más" y '_' implica" exactamente uno ". Eso me permite descartar todo excepto el último elemento, ya que ahora describí explícitamente la estructura de la lista. Entiendo que probablemente sea azúcar sintáctico y que la recursión/retroceso real esté oculta debajo del capó. – abcd
@yoda No hay forma de hacer esto (que yo sepa, al menos) con la coincidencia de patrones de Haskell. Eso parece ser una característica específica de Mathematica. En general, el diseño de Haskell generalmente evita tipos de datos "especiales" que obtienen muchas campanas y silbatos extras (excepto por la agradable sintaxis para listas y tuplas). Haskell prefiere las funciones para agregar más equipaje al idioma. – sabauma
Gracias, eso es lo que pensé. También puedo apreciar esta filosofía ... me obliga a pensar un poco más. Al menos, ¡no tengo que preocuparme por aprender programación funcional al mismo tiempo! :) – abcd