Ich bin kürzlich auf Situationen gestoßen, in denen ich eine Prädikatfunktion an eine andere Funktion übergeben muss, und die gesuchte Logik lautet häufig: "Stimmt dieser Wert mit diesem Muster überein?"
Musterabgleich scheint in Deklarationen, do
Blöcken und Listenverständnissen bevorzugt zu sein , aber es gibt eine Reihe von Funktionen, die ein Prädikat annehmen a -> Bool
, bei denen es sehr praktisch wäre, ein Muster irgendwie zu übergeben. Zum Beispiel takeWhile
, until
, find
, span
, usw.
Bisher habe ich \a -> case a of MyCons _ -> True; otherwise -> False
eine benannte Funktion a la gemacht oder geschrieben, let myPred (MyCons _) = True; myPred _ = False in
aber beide scheinen schrecklich hässlich und nicht sehr idiomatisch zu sein. Der "offensichtliche" (und falsche) Weg wäre so etwas wie, \(MyCons _) -> True
aber das wirft natürlich den Fehler auf, parteiisch zu sein, und selbst dann scheint es einen saubereren Weg zu geben.
Gibt es eine prägnantere / sauberere Möglichkeit, so etwas zu tun? Oder gehe ich die Dinge völlig falsch an?
let myPred...
Stil für schlecht halte , aber er fühlt sich viel ausführlicher an, als ich es für eine sehr einfache Idee erwarten würde, was mich zu der Frage führt, ob ich den falschen Baum belle.
maybe :: b -> (a -> b) -> Maybe a -> b
und zu definieren und sie bool :: a -> a -> Bool -> a
dann mit Booleschen produzierenden Funktionen als Argument (e) zu verwenden. zB myCons z f (MyCons x) = f x ; myCons z f _ = z
dann anrufen myCons False (const True) aMyConsValue
. Dies ist fast das, was Sie geschrieben haben. Es ist nur eine weitere Ebene der "Indirektion" / "Abstraktion" über funktionale Argumente eingebaut.
let
Klausel, die Sie nicht mögen , sehr zufrieden - obwohl ich die entsprechendewhere
Klausel bevorzuge , damit die Hauptdefinition nicht durcheinander gerät. Wenn Sie dieses Dienstprogramm mehr als einmal benötigen, definieren Sie es natürlich als Funktion der obersten Ebene.