2013-03-06 12 views
6

Trovo che molte cose che faccio jigger da solo e che sembrano utili in realtà hanno un'implementazione standard che non conoscevo, quindi ero curioso se qualcuno potesse dire di aver visto questo tipo di cose usate prima :Questa funzione Haskell è conosciuta/implementata come un altro nome?

Ci vuole una funzione monadica e si piega fino a quando un predicato è scelto da alternativa poi restituisce il risultato del predicato:

until :: (Monad m, Alternative m) => (a -> m a) -> (a -> m c) -> a -> m c 
f `until` p = \a -> (f >=> (p `altF` (until f p))) a 
    where f1 `altF` f2 = \a -> f1 a <|> f2 a 

mi rendo conto che il nome è una collisione preludio, io probabilmente chiamatelo in un altro modo, ma pensavo che prima avrei visto se c'è già una funzionalità simile in una libreria standard di cui non so nulla ...

Immagino anche di essere curioso di sapere se l'alternativa compositiva che ho scritto sia definita altrove o se qualcuno di questo aspetto della funzionalità sembra fuorviante. Ma il punto cruciale della mia domanda è, è implementato altrove o è qualcosa di molto simile implementato altrove forse

+0

Si potrebbe voler usare 'MonadPlus' piuttosto che i vincoli' Monad' e 'Alternative' combinati. –

+0

@pelotom È possibile definire l'alternativa in termini di MonadPlus? Non ero a conoscenza, ho appena preso la mia firma direttamente da GHCi –

+1

Definiscono API diverse ma svolgono ruoli simili ... 'Alternativa':' Applicativa' :: 'MonadPlus':' Monade'. –

risposta

7

Esiste un numero sorprendentemente elevato di funzioni di comodità che non si trovano nel Preludio o nelle librerie standard, ma forse dovrebbero esserlo. Non mi preoccuperei troppo di reimplementare alcuni se li trovi utili.

notando che altF è equivalente a liftA2 (<|>), si potrebbe scrivere più simile a questo:

till :: (Monad m, Alternative m) => (a -> m a) -> (a -> m b) -> a -> m b 

-- To do f till p is to first do f; then either p, or f till p. 
f `till` p = f >=> (<|>) <$> p <*> f `till` p 

e notando che (Monad m, Alternative m) è molto simile a quello MonadPlus m, è possibile semplificare un po 'il tipo:

till :: MonadPlus m => (a -> m a) -> (a -> m b) -> a -> m b 
f `till` p = f >=> mplus <$> p <*> f `till` p 

C'è una funzione simile denominata untilM in Control.Monad.Loops che utilizza un predicato Bool e un trasformatore LoopT e xists per il loop arbitrario in Control.Monad.Trans.Loop. Ma no, questa particolare funzione non sembra essere ancora famosa.

Problemi correlati