No Haskell, posso usar o tipo a -> Maybe b
para modelar uma função que retorna um valor do tipo b
ou não retorna nada (falha).
Se eu tiver tipos a1, ..., a(n+1)
e funções f1, ..., fn
, com fi :: ai -> Maybe a(i+1)
para todos i
, 1 <= i <= n
posso encadear as funções usando o >>=
operador da Maybe
mônada e escrever:
f1 x >>= f2 >>= f3 >>=... >>= fn
O >>=
operador garante que cada função seja aplicada desde que seu predecessor retorne um valor significativo. Assim que uma função na cadeia falha, a cadeia inteira falha (retorna Nothing
) e outras funções na cadeia não são avaliadas.
Eu tenho um padrão um pouco semelhante no qual desejo tentar várias funções na mesma entrada e retornar assim que uma função for bem-sucedida . Se todas as funções falharem (retornar Nothing
), todo o cálculo falhará. Mais precisamente, tenho funções f1, ..., fn :: a -> Maybe b
e defino a função
tryFunctions :: [a -> Maybe b] -> a -> Maybe b
tryFunctions [] _ = Nothing
tryFunctions (f : fs) x = case f x of
Nothing -> tryFunctions fs x
r@(Just _) -> r
Em certo sentido, isso é duplo para a Maybe
mônada, pois um cálculo para no primeiro sucesso, e não na primeira falha.
Obviamente, posso usar a função que escrevi acima, mas fiquei pensando se há uma maneira melhor, bem estabelecida e idiomática de expressar esse padrão em Haskell.
Alternative
que é o operador símbolo infix <|>
e é definido em termos de uma Monoid
return f1 ?? f2 ?? f3 ?? DefaultValue;