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.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow