Haskell Language
Sintaxis en funciones
Buscar..
Guardias
Se puede definir una función utilizando guardas, que se puede pensar en clasificar el comportamiento de acuerdo con la entrada.
Tome la siguiente definición de función:
absolute :: Int -> Int -- definition restricted to Ints for simplicity
absolute n = if (n < 0) then (-n) else n
Podemos reorganizarlo utilizando guardas:
absolute :: Int -> Int
absolute n
| n < 0 = -n
| otherwise = n
En este contexto, de lo otherwise
es un alias significativo para True
, por lo que siempre debe ser la última guardia.
La coincidencia de patrones
Haskell admite expresiones de coincidencia de patrones tanto en la definición de funciones como a través de declaraciones de case
.
Una declaración de caso es muy similar a un interruptor en otros idiomas, excepto que admite todos los tipos de Haskell.
Comencemos simple:
longName :: String -> String
longName name = case name of
"Alex" -> "Alexander"
"Jenny" -> "Jennifer"
_ -> "Unknown" -- the "default" case, if you like
O bien, podríamos definir nuestra función como una ecuación que sería la coincidencia de patrones, sin usar una declaración de case
:
longName "Alex" = "Alexander"
longName "Jenny" = "Jennifer"
longName _ = "Unknown"
Un ejemplo más común es con el tipo 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
La coincidencia de patrones también se puede utilizar en listas:
isEmptyList :: [a] -> Bool
isEmptyList [] = True
isEmptyList _ = False
addFirstTwoItems :: [Int] -> [Int]
addFirstTwoItems [] = []
addFirstTwoItems (x:[]) = [x]
addFirstTwoItems (x:y:ys) = (x + y) : ys
En realidad, la coincidencia de patrones se puede utilizar en cualquier constructor para cualquier clase de tipo. Por ejemplo, el constructor para listas es :
y para tuplas ,
Usando donde y guardias
Teniendo en cuenta esta función:
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!"
Podemos usar where
evitar la repetición y hacer que nuestro código sea más legible. Vea la función alternativa a continuación, usando 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)
Como se observó, utilizamos el punto where
al final del cuerpo de la función, eliminamos la repetición del cálculo ( hourlyRate * (weekHoursOfWork * 52)
) y también usamos where
organizar el rango de salario.
El nombramiento de sub-expresiones comunes también se puede lograr con la let
expresiones, pero sólo el where
la sintaxis hace posible que los guardias que se refieren a las sub-expresiones nombradas.