Ho incontrato il seguente schema durante la programmazione in Haskell (ma lo schema potrebbe verificarsi in qualsiasi lingua che supporta elenchi, tipi di opzioni e mappatura di una funzione su un elenco). Ho tipi a
e b
e una funzione
f :: a -> Maybe b
Ora voglio definire una funzione che mappa f in un elenco di tipo [a]
, ma non mi interessa avere un risultato di tipo [Maybe b]
. Piuttosto, voglio avere Just [y1, ..., yn]
, se [f(x1), ..., f(xn)] == [Just y1, ..., Just yn]
e Nothing
altrimenti (cioè se f(xi) == Nothing
per almeno un i). Quindi il risultato deve essere di tipo Maybe [b]
.
Ho risolto questo problema utilizzando la seguente funzione di supporto:
combine :: Maybe b -> Maybe [b] -> Maybe [b]
combine me ml = do
l <- ml
e <- me
Just (e : l)
e poi
g :: (a -> Maybe b) -> [a] -> Maybe [b]
g f xs = foldr combine (Just []) (map f xs)
Quindi, ad esempio, se ho
f x = if x > 0 then Just x else Nothing
xs0 = [1, 2, 3, 4]
xs1 = [-1, -2, 3, 4]
xs2 = [-1, -2, -3, -4]
poi
map f xs0 = [Just 1, Just 2, Just 3, Just 4]
g f xs0 = Just [1, 2, 3, 4]
map f xs1 = [Nothing, Nothing, Just 3, Just 4]
g f xs1 = Nothing
map f xs2 = [Nothing, Nothing, Nothing, Nothing]
g f xs2 = Nothing
La soluzione con combine
e foldr
funziona, ma volevo chiederti se sei a conoscenza di una soluzione più compatta per trasformare una [Maybe a]
in una Maybe [a]
come descritto sopra.