2014-09-10 13 views
6

Ich möchte die mindestens zwei vielleicht Werte erhalten, oder wenn man nichts bekommen, ist das nicht nichts ein, oder nichts zurück, wenn beide Eingänge nichts sind. Ich kann eine einfache Funktion schreiben, um dies zu tun, aber ich vermute, es gibt eine Möglichkeit, dies zu tun, ohne eine benutzerdefinierte Funktion zu schreiben. Entschuldigung, wenn dies eine kleine Frage ist, aber gibt es einen einfacheren Weg als die Verwendung dieser benutzerdefinierten Funktion?mindestens zwei 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

bevor ich von diesem pigworker downvoted;) ... was ist mit: 'lassen minM a b = vielleicht ein Nur $ vielleicht b Nur $ min a b '? – Carsten

+0

Vielleicht [nur das] (http://ideone.com/GH4K7K) –

+0

n.m, das funktioniert, aber es ist nicht einfacher als das, womit ich anfange. – clay

Antwort

3

Sie können nicht die Applicative oder Monad Beispiel dafür verwenden, da jede Nothing in diesen Kontexten wird Ihr Gesamtergebnis ist eine Nothing haben. Das heißt, der Begriff "einfacher" ist sehr eigenwillig, und Ihre Funktion ist in Ordnung, wie es ist.

+2

Hinweis: Community-Wiki seit "einfacher" ist sehr eigenwillig. – Zeta

+0

Da 'max' so funktioniert, wie @clay es möchte (" lieber "als" Nichts "), würde @clay vielleicht Data.Ord.Down verwenden, dann hätten sie das Verhalten, das sie wollen, während sie immer noch" einfacher "sind wie die anderen antworten wollen. – radomaj

3

Sie können schreiben mit der Alternative Instanz Maybe:

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

Alternativ Sie maxBound als Standard verwenden könnte, so dass es dann immer wählen, die andere:

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

Aber ich don empfehle das nicht.

17

Es ist möglich, die Spezifikation mit Operatoren von Control.Applicative zu erfüllen.

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

wo die <|> für Maybe Geräte "Präferenz"

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

Die Sache ist

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

aber

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

, die in irgendeiner incorre geführt hat Antwort auf diese Frage. Wenn Sie <|> verwenden, können Sie den berechneten Wert min bevorzugen, wenn dieser verfügbar ist, aber mit einem der beiden Werte wiederherstellen, wenn nur einer Just ist.

Aber sollten Sie fragen, ob es angemessen ist, Maybe auf diese Weise zu verwenden. Mit der unrühmlichen Ausnahme seiner Monoid Instanz ist Maybe eingerichtet, um fehleranfällige Berechnungen zu modellieren. Was Sie hier haben, ist die Erweiterung eines bestehenden Ord mit einem "top" -Element.

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

und Sie werden feststellen, dass min für Topped x ist genau das, was Sie brauchen. Es ist gut, an Typen nicht nur die Darstellung von Daten, sondern auch die Ausstattung von Daten mit Struktur zu denken. Nothing steht normalerweise für eine Art von Fehler, daher ist es möglicherweise besser, einen anderen Typ für Ihren Zweck zu verwenden.

+0

true, aber Sie brauchen eine andere Datenstruktur für 'max' ... –

+3

' Topped x' hat ein sinnvolles 'max', aber wenn Sie stattdessen ein * bottom * -Element hinzufügen möchten, dann ändert sich die beabsichtigte Semantik Warum sollte der Typ gleich bleiben? Natürlich könnten wir einmal die Konstruktion "Monoid aus einer Halbgruppe machen" machen, dann "max", "min" usw. als Halbgruppenstrukturen umhüllen. – pigworker

+1

'min <$> a <*> b == min a b' auf' Maybe's. Letzteres sieht jedoch "golfiger" als "einfacher" aus ... – chi

Verwandte Themen