2014-09-10 7 views
6

Voglio ottenere il minimo di due valori, o se uno è niente, ottenere il non nulla, o non restituire nulla se entrambi gli input non sono nulla. Posso scrivere una semplice funzione per farlo, ma sospetto che ci sia un modo per farlo senza scrivere una funzione personalizzata. Scusa, se questa è una domanda insignificante, ma esiste un modo più semplice rispetto all'utilizzo di questa funzione personalizzata?Minimo di due Maybes

minMaybe :: Ord a => Maybe a -> Maybe a -> Maybe a 
minMaybe Nothing b = b 
minMaybe a Nothing = a 
minMaybe (Just a) (Just b) = Just $ min a b 
+0

prima di essere svalutato da quel pigworker;) ... che dire: "lascia minM a b = forse un Just $ forse b Just $ min a b '? – Carsten

+0

Forse [solo questo] (http://ideone.com/GH4K7K) –

+0

n., Che funziona, ma non è più semplice quello che sto iniziando. – clay

risposta

3

Non è possibile utilizzare la Applicative, o Monad esempio per questo, dal momento che ogni Nothing in quei contesti avrà il risultato totale è un Nothing. Detto questo, il termine "più semplice" è altamente raccomandato e la tua funzione va bene così com'è.

+2

Nota: la wiki della comunità poiché "più semplice" è altamente motivata. – Zeta

+0

Dato che 'max' funziona come @clay lo vorrebbe (" preferendo "solo valori a Nothings), forse se @clay avesse usato Data.Ord.Down avrebbero avuto il comportamento che volevano, mentre erano ancora" più semplici "nel in modo che le altre risposte lo vogliano. – radomaj

3

È possibile scrivere utilizzando l'istanza di AlternativeMaybe:

minMaybe a b = liftA2 min a b <|> a <|> b 

In alternativa, è possibile utilizzare maxBound come predefinito, in modo che sarà sempre scegliere l'altro:

minMaybe a b = liftA2 min (d a) (d b) 
    where d x = x <|> Just maxBound 

Ma don lo raccomando.

17

È possibile soddisfare le specifiche utilizzando gli operatori da Control.Applicative.

myMin :: Ord x => Maybe x -> Maybe x -> Maybe x 
myMin a b = min <$> a <*> b <|> a <|> b 

dove il <|> per Maybe attrezzi "preferenza"

Nothing <|> b = b 
a  <|> _ = a 

La cosa è

min <$> Just a <*> Just b = Just (min a b) 

ma

min <$> Just a <*> Nothing = Nothing 

che ha portato in qualche incorre ct risponde a questa domanda. L'utilizzo di <|> consente di preferire il valore calcolato min quando è disponibile, ma ripristinarlo individualmente quando uno solo è Just.

Ma si dovrebbe chiedere se è opportuno utilizzare Maybe in questo modo. Con l'ingloriosa eccezione della sua istanza Monoid, Maybe è impostato per modellare calcoli soggetti a errori. Quello che hai qui è l'estensione di uno Ord esistente con un elemento "top".

data Topped x = Val x | Top deriving (Show, Eq, Ord) 

e troverete che min per Topped x è proprio quello che serve. È bello pensare ai tipi non solo alla rappresentazione dei dati ma all'equipaggiamento dei dati con struttura. Nothing rappresenta solitamente un tipo di errore, quindi potrebbe essere preferibile utilizzare un tipo diverso per lo scopo.

+0

true, ma avrete bisogno di una struttura dati differente per 'max' ... –

+3

' Topped x' ha un 'max 'ragionevole, ma se volete aggiungere un elemento * bottom * invece, la semantica desiderata cambia, quindi perché il tipo dovrebbe rimanere lo stesso? Certo, potremmo fare una volta la costruzione "fai un monoide da un semigruppo", quindi avvolgere 'max',' min', ecc. Come strutture di semigruppo. – pigworker

+1

'min <$> a <*> b == min a b' su' Forse's. Quest'ultimo però sembra più "golfato" che "più semplice" ... – chi