Expresar un patrón “caso … de” de forma más elegante en Haskell.
Me encontré con un patrón que creo que puede ser expresado de manera más elegante:
Tengo dos funciones f1, f2:: Int -> Int
(su implementación no es relevante), y un process:: Int -> Int
que hace lo siguiente:
- Si
f1 x
produce unx1
diferente dex
, entonces repetir el proceso conx1
. - De lo contrario, si
f2 x
produce unx2
diferente dex
, entonces repetir el proceso conx2
. - Finalmente, detener el proceso y devolver
x
.
Mi implementación de case ... of
es la siguiente:
f1:: Int -> Int
f1 = undefined
f2:: Int -> Int
f2 = undefined
process:: Int -> Int
process x =
case f1 x of
x ->
case f2 x of
x -> x
x' -> process x'
x' -> process x'
que produce las siguientes advertencias:
so.hs:13:17: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
13 | x' -> process x'
| ^^^^^^^^^^^^^^^^
so.hs:14:9: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
14 | x' -> process x'
| ^^^^^^^^^^^^^^^^
¿Alguien puede arrojar algo de luz sobre qué patrones están superpuestos y cómo implementar process
de manera más elegante?
davy.ai
Los patrones que se superponen son
x' -> procesar x'
en ambos casos. Esto se debe a que sif1 x
producex'
diferente dex
, entonces se ejecutará el primer caso y se verificará el segundo caso, pero sif2 x
también producex'
diferente dex
, entonces el segundo caso se ejecutará nuevamente y se hará la misma llamada recursivaprocesar x'
. Esto se puede solucionar fusionando los dos casos anidados en uno solo utilizando la funciónorElse
del móduloControl.Monad
, que prueba el segundo argumento si el primero devuelveNothing
:Esta implementación primero calcula
x1
yx2
y luego utiliza una única expresióncase
con tres guardias para verificar si alguno de ellos es diferente dex
. Si es así, se llama aprocesar
recursivamente con el nuevo valor, de lo contrario se devuelvex
. Esto evita el mensaje de advertencia de patrones superpuestos y hace que el código sea ligeramente más conciso y legible.