Haskell Language
Syntax in Funktionen
Suche…
Wachen
Eine Funktion kann mithilfe von Guards definiert werden, die das Verhalten anhand der Eingabe klassifizieren.
Nehmen Sie die folgende Funktionsdefinition an:
absolute :: Int -> Int -- definition restricted to Ints for simplicity
absolute n = if (n < 0) then (-n) else n
Wir können es mit Hilfe von Wachen neu anordnen:
absolute :: Int -> Int
absolute n
| n < 0 = -n
| otherwise = n
In diesem Zusammenhang ist otherwise
ein sinnvoller Alias für True
, daher sollte es immer die letzte Wache sein.
Musterabgleich
Haskell unterstützt Mustervergleichsausdrücke sowohl bei der Funktionsdefinition als auch bei den case
Anweisungen.
Eine Case-Anweisung ähnelt einem Schalter in anderen Sprachen, unterstützt jedoch alle Typen von Haskell.
Fangen wir einfach an:
longName :: String -> String
longName name = case name of
"Alex" -> "Alexander"
"Jenny" -> "Jennifer"
_ -> "Unknown" -- the "default" case, if you like
Oder wir können unsere Funktion als eine Gleichung definieren, bei der es sich um eine Musterübereinstimmung handelt, nur ohne eine case
Anweisung:
longName "Alex" = "Alexander"
longName "Jenny" = "Jennifer"
longName _ = "Unknown"
Ein häufigeres Beispiel ist der Typ Maybe
:
data Person = Person { name :: String, petName :: (Maybe String) }
hasPet :: Person -> Bool
hasPet (Person _ Nothing) = False
hasPet _ = True -- Maybe can only take `Just a` or `Nothing`, so this wildcard suffices
Der Musterabgleich kann auch für Listen verwendet werden:
isEmptyList :: [a] -> Bool
isEmptyList [] = True
isEmptyList _ = False
addFirstTwoItems :: [Int] -> [Int]
addFirstTwoItems [] = []
addFirstTwoItems (x:[]) = [x]
addFirstTwoItems (x:y:ys) = (x + y) : ys
Eigentlich kann Pattern Matching für jeden Konstruktor für jede Typenklasse verwendet werden. ZB der Konstruktor für Listen ist :
und für Tupeln ,
Wo und Wachen verwenden
Gegeben diese Funktion:
annualSalaryCalc :: (RealFloat a) => a -> a -> String
annualSalaryCalc hourlyRate weekHoursOfWork
| hourlyRate * (weekHoursOfWork * 52) <= 40000 = "Poor child, try to get another job"
| hourlyRate * (weekHoursOfWork * 52) <= 120000 = "Money, Money, Money!"
| hourlyRate * (weekHoursOfWork * 52) <= 200000 = "Ri¢hie Ri¢h"
| otherwise = "Hello Elon Musk!"
Wir können verwendet werden, where
die Wiederholung zu vermeiden und unseren Code besser lesbar machen. Siehe die alternative Funktion unten, mit where
:
annualSalaryCalc' :: (RealFloat a) => a -> a -> String
annualSalaryCalc' hourlyRate weekHoursOfWork
| annualSalary <= smallSalary = "Poor child, try to get another job"
| annualSalary <= mediumSalary = "Money, Money, Money!"
| annualSalary <= highSalary = "Ri¢hie Ri¢h"
| otherwise = "Hello Elon Musk!"
where
annualSalary = hourlyRate * (weekHoursOfWork * 52)
(smallSalary, mediumSalary, highSalary) = (40000, 120000, 200000)
Wie festgestellt, verwenden wir die in where
am Ende des Funktionskörpers , die Wiederholung der Berechnung (Eliminieren hourlyRate * (weekHoursOfWork * 52)
) , und wir auch verwendet , where
den Gehaltsbereich zu organisieren.
Die Benennung allgemeiner Unterausdrücke kann auch mit let
Ausdrücken erreicht werden, aber nur durch die where
Syntax können Guards auf diese genannten Unterausdrücke verweisen.