guards guardas haskell f# functional-programming pattern-matching guard-clause

guardas - haskell function declaration syntax



Patrón que coincide con valores idénticos (5)

Me pregunté si es posible hacer coincidir los mismos valores varias veces con las funciones de coincidencia de patrones de los lenguajes de programación funcionales (Haskell / F # / Caml).

Solo piensa en el siguiente ejemplo:

plus a a = 2 * a plus a b = a + b

La primera variante se llamará cuando la función se invoque con dos valores similares (que se almacenarán en a ).

Una aplicación más útil sería esta (simplificando un AST).

simplify (Add a a) = Mult 2 a

Pero Haskell rechaza estos códigos y me advierte de definiciones conflictivas para a - Tengo que hacer comprobaciones explícitas de caso / si en lugar de averiguar si la función tiene valores idénticos. ¿Hay algún truco para indicar que una variable con la que quiero hacer coincidir ocurrirá varias veces?


Acabo de consultar los hilos de la lista de correo que figuran en la respuesta de Thomas, y la primera respuesta en uno de ellos tiene sentido, y explica por qué ese "patrón" no tendría mucho sentido en general: ¿qué sucede si a es una función ? (En general, es imposible verificar si dos funciones son iguales).


Esto se llama un patrón no lineal . Ha habido varios hilos en la lista de correo de haskell-cafe sobre esto, no hace mucho. Aquí hay dos:

http://www.mail-archive.com/[email protected]/msg59617.html

http://www.mail-archive.com/[email protected]/msg62491.html

En pocas palabras: no es imposible de implementar, pero se decidió no hacerlo por simplicidad.

Por cierto, no es necesario if o case para solucionar esto; La forma (ligeramente) más limpia es usar un protector:

a `plus` b | a == b = 2*a | otherwise = a+b


Haskell no hace la unificación.


He implementado un nuevo lenguaje de programación funcional que puede manejar patrones no lineales en Haskell.

https://github.com/egison/egison

En mi idioma, su función plus en escrito como sigue.

(define $plus (match-lambda [integer integer] {[[$a ,a] (* a 2)] [[$a $b] (+ a b)]}))


No puede tener dos parámetros con el mismo nombre para indicar que deben ser iguales, pero puede usar guards para distinguir casos como este:

plus a b | a == b = 2 * a | otherwise = a + b

Esto es más flexible ya que también funciona para condiciones más complicadas que la simple igualdad.