Zoeken…


Guards

Een functie kan worden gedefinieerd met behulp van bewakers, waarvan kan worden gedacht dat het gedrag wordt geclassificeerd op basis van invoer.

Neem de volgende functiedefinitie:

absolute :: Int -> Int  -- definition restricted to Ints for simplicity
absolute n = if (n < 0) then (-n) else n

We kunnen het herschikken met behulp van bewakers:

absolute :: Int -> Int
absolute n 
  | n < 0 = -n
  | otherwise = n

In deze context is otherwise een zinvolle alias voor True , dus het moet altijd de laatste bewaker zijn.

Patroon matching

Haskell ondersteunt patroonuitdrukkingen in zowel functiedefinitie als via case statements.

Een case-statement lijkt veel op een schakelaar in andere talen, behalve dat deze alle typen Haskell ondersteunt.

Laten we eenvoudig beginnen:

longName :: String -> String
longName name = case name of
                   "Alex"  -> "Alexander"
                   "Jenny" -> "Jennifer"
                   _       -> "Unknown"  -- the "default" case, if you like

Of we zouden onze functie kunnen definiëren als een vergelijking die patroonovereenkomst zou zijn, alleen zonder een case statement te gebruiken:

longName "Alex"  = "Alexander"
longName "Jenny" = "Jennifer"
longName _       = "Unknown"

Een meer algemeen voorbeeld is met het Maybe type:

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

Patroonovereenkomst kan ook worden gebruikt in lijsten:

isEmptyList :: [a] -> Bool
isEmptyList [] = True
isEmptyList _  = False

addFirstTwoItems :: [Int] -> [Int]
addFirstTwoItems []        = []
addFirstTwoItems (x:[])    = [x]
addFirstTwoItems (x:y:ys)  = (x + y) : ys

Eigenlijk kan Pattern Matching worden gebruikt op elke constructor voor elke typeklasse. De constructor voor lijsten is bijvoorbeeld : en voor tupels ,

Waar en bewakers gebruiken

Gegeven deze functie:

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!"

We kunnen gebruiken where de herhaling te voorkomen en onze code leesbaarder maken. Zie de alternatieve functie hieronder, 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)

Zoals opgemerkt, gebruiken wij where het einde van de functie lichaam waardoor de herhaling van de berekening ( hourlyRate * (weekHoursOfWork * 52) ) en was ook where het salaris organiseren.

Het benoemen van algemene sub-expressies kan ook worden bereikt met let expressies, maar alleen where syntaxis het mogelijk maakt voor bewakers om te verwijzen naar die sub-expressies.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow