En Haskell, puedo usar el tipo a -> Maybe bpara modelar una función que devuelve un valor de tipo bo 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 <= npuedo encadenar las funciones usando el >>=operador de la Maybemó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 by 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 Maybemó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.

return f1 ?? f2 ?? f3 ?? DefaultValue;Alternativees el operador de infijo de símbolo<|>y se define en términos de un monoideRespuestas:
Dado un conjunto cerrado (número fijo de elementos)
Scon elementos{a..z}y un operador binario*:Hay un único elemento de identidad
ital que:forall x in S: i * x = x = x * iEl operador es asociativo de manera que:
forall a, b, c in S: a * (b * c) = (a * b) * cTienes un monoide.
Ahora, dado cualquier monoide, puede definir una función binaria
fcomo:Lo que esto significa es que, por ejemplo, el
Maybemonoide (Nothinges el elemento de identidad indicado anteriormente comoi):Sorprendentemente, no puedo encontrar esta función precisa en las bibliotecas predeterminadas, lo que probablemente se deba a mi propia inexperiencia. Si alguien más puede ser voluntario en esto, lo agradecería sinceramente.
Aquí está la implementación que deduje de la mano del ejemplo anterior:
Ejemplo:
Entonces, si desea utilizar una lista de funciones como entrada ...
ejemplo:
fuente
<|>trata la identidad de un monoide de una manera especial. ¿No podría uno elegir un elemento arbitrario de un conjunto arbitrario para desempeñar ese papel especial? ¿Por qué el conjunto tiene que ser un monoide y el elemento especial es<|>su identidad?<|>no confía en monoide y tengo todo esto mezclado. Se basa enAlternativetypeclass. Para estar seguro - Estoy mirando mi propia respuesta y darse cuenta de que no está del todo bien como[1,2] <|> [3]da la inesperada[1,2,3]por lo que todo lo relacionado con el uso de la clase de tipo monoid para identificar una identidad que es correcto - y la otra clave es la asociatividad es necesario para obtener el comportamiento esperado , tal vezAlternativeno da el comportamiento que pensé de la mano ...fpara ver por qué la asociatividad es una necesidad.fuente
Maybe... Mi solución está limitadaEq, de alguna manera siento que a los dos nos falta algo disponible enMonoidgeneral ...either?Monoidque cualquier cosa con un elemento de identidad pueda tener un conjunto de 2 funciones (creo que este es un tipo de campo binario), donde una de las funciones elige identidad sobre todas las demás, y la otra función siempre elige El elemento de no identidad. Simplemente no sé cómo hacer esto sinEqsaber qué valor esidentityo no ... obviamente en los monoides aditivos o multiplicativos obtienes la función de escalera por defecto (siempre elige elementos que no sean de identidad usando la función binaria de monoides)foldMapse puede usar en lugar demconcat . mapEsto se parece mucho a reemplazar el fracaso por una lista de éxitos
Estás hablando en
Maybe alugar de hacerlo[a], pero en realidad son muy similares: podemos pensarMaybe aque son como[a], excepto que puede contener como máximo un elemento (es decir,Nothing ~= []yJust x ~= [x]).En el caso de las listas,
tryFunctionssería muy simple: aplique todas las funciones al argumento dado y luego concatene todos los resultados juntos.concatMaphará esto muy bien:De esta manera, podemos ver que el
<|>operador paraMaybeactúa como concatenación para 'listas con como máximo un elemento'.fuente
En el espíritu de Conal, divídalo en operaciones más pequeñas y simples.
En este caso,
asumdesdeData.Foldablehace la parte principal.Alternativamente, a la respuesta de Jimmy Hoffa puede usar la
Monoidinstancia,(->)pero luego necesita unaMonoidinstanciaMaybey la estándar no hace lo que desea. ¿QuieresFirstpartirData.Monoid.(O
mconcatpara una versión anterior y más especializada defold).fuente