En Haskell, puedo usar el tipo a -> Maybe b
para modelar una función que devuelve un valor de tipo b
o no devuelve nada (falla).
Si tengo tipos a1, ..., a(n+1)
y funciones f1, ..., fn
, con fi :: ai -> Maybe a(i+1)
for all i
, 1 <= i <= n
puedo encadenar las funciones usando el >>=
operador de la Maybe
mónada y escribir:
f1 x >>= f2 >>= f3 >>=... >>= fn
El >>=
operador se asegura de que cada función se aplique siempre que su predecesor haya devuelto un valor significativo. Tan pronto como falla una función en la cadena, la cadena completa falla (retorna Nothing
) y no se evalúan otras funciones en la cadena.
Tengo un patrón algo similar en el que quiero probar varias funciones en la misma entrada y regresar tan pronto como una función tenga éxito . Si todas las funciones fallan (retorno Nothing
), todo el cálculo debería fallar. Más precisamente, tengo funciones f1, ..., fn :: a -> Maybe b
y defino la función
tryFunctions :: [a -> Maybe b] -> a -> Maybe b
tryFunctions [] _ = Nothing
tryFunctions (f : fs) x = case f x of
Nothing -> tryFunctions fs x
r@(Just _) -> r
En cierto sentido, esto es dual para la Maybe
mónada en que un cálculo se detiene en el primer éxito en lugar de en el primer fracaso.
Por supuesto, puedo usar la función que he escrito anteriormente, pero me preguntaba si hay una forma mejor, bien establecida e idiomática de expresar este patrón en Haskell.
Alternative
es el operador de infijo de símbolo <|>
y se define en términos de un monoide
return f1 ?? f2 ?? f3 ?? DefaultValue;