Haskell Language
Syntaxis in functies
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.