per il sequenziamento in Haskell, si hanno le funzioni >>=
e sequence
:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
sequence :: Monad m => [m a] -> m [a]
La funzione >>=
o BIND ha un'azione monadica, estrae il valore da esso e lo nutre in una funzione che restituisce una nuova azione monadica. La funzione sequence
accetta un elenco di azioni monadiche dello stesso tipo e le esegue tutte, aggregando i risultati e avvolgendoli in un'unica azione.
per l'iterazione avete mapM
e forM
(forM = flip mapM
)
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
I mapM
e forM
funzioni sono per l'applicazione di una funzione che restituisce un azione per ogni elemento in un elenco, aggregando i risultati come una singola azione.
Per la selezione, presumo che intendiate condizionali, che sono implementati in Haskell come espressioni if-the-else. Possono essere usati direttamente nelle espressioni monadiche allo stesso modo in cui possono essere usati in espressioni pure. Tuttavia, puoi anche utilizzare alcune monadi per eseguire scelte o almeno gestire errori. Il più facile da Grok è la monade Maybe
:
data Maybe a = Nothing | Just a
instance Monad Maybe where
return a = Just a
(Just a) >>= f = f a
Nothing >>= f = Nothing
Ha un'interfaccia molto semplice implementazione. In sostanza, se provi a sequenziare uno Nothing
in qualcos'altro, restituirà Nothing
ogni volta. Questo vi dà l'idea del fallimento cortocircuito:
lookup :: Eq a => a -> [(a, b)] -> Maybe b
-- Looks up a value in a key-value association list
myFunc :: Int -> [(String, Int)] -> Maybe Int
myFunc mult assocList = do
i <- lookup "foo" assocList
j <- lookup "bar" assocList
return $ i * mult + j
Qui, se la ricerca per "foo"
non riesce, l'myFunc
restituisce immediatamente Nothing
. Analogamente, se la ricerca di "bar"
non riesce, myFunc
restituisce immediatamente Nothing
. È solo quando entrambe le ricerche riescono a fare lo myFunc
fare qualsiasi calcolo. Questo fornisce una sorta di "gestione degli errori". C'è una monade simile Either a
data Either a b = Left a | Right b
instance Monad (Either a) where
return a = Right a
(Right a) >>= f = f a
(Left a) >>= f = Left a
che funziona molto simile, ad eccezione del valore di "fallimento" può portare un po 'di contesto, come ad esempio un messaggio di errore stringa o lo stato del calcolo al punto di errore.
Does '>> =' garantisce davvero il sequenziamento o è solo il comportamento delle monadi più comuni? – kqr
@kqr Non garantisce il sequenziamento della valutazione, se è questo che stai chiedendo.Il motivo è perché l'ordine di valutazione dipende dalla definizione di '(>> =)', e non tutte le implementazioni di '(>> =)' valutano il primo argomento prima del secondo. –
@kqr Non garantisce il sequenziamento, ma è la funzione che ci consente di usare la notazione 'do', che è quella che ho interpretato come una domanda. Poiché bind definisce essenzialmente il punto e virgola (implicito) per ogni azione in una dichiarazione do, ci consente di definire un aspetto del flusso di controllo per un particolare blocco di codice. – bheklilr