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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow