Ejemplo de valor:
ghci> 2
Ejemplo de aplicación de una función a un valor:
ghci> (+3) 2
5
Ejemplo de un valor en un contexto:
ghci> Just 2
Idea básica: el resultado de aplicar una función a un valor depende del contexto en el que se encuentra dicho valor.
Contextos definidos por Maybe:
data Maybe a = Nothing | Just a
Las funciones no se aplican a valores en contextos:
ghci> (+3) (Just 2)
da error.
Ejemplo de evaluación en contextos con fmap
ghci> fmap (+3) (Just 2)
Just 5
Tipo de fmap:
ghci> :type fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Un functor es cualquier clase de tipos que define cómo aplicar fmap.
ghci> :info Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
Los functores aplican funciones a valores en contextos.
Maybe es un functor definido en Data.Maybe por
instance Functor Maybe where
fmap func (Just val) = Just (func val)
fmap func Nothing = Nothing
Ejemplos de evaluación de fmap en Maybe:
ghci> fmap (+3) (Just 2)
Just 5
ghci> fmap (+3) Nothing
Nothing
El operador <$> es la versión infija de fmap. Está definido en Control.Applicative
ghci> (+3) <$> (Just 2)
Just 5
ghci> (+3) <$> Nothing
Nothing
Las listas son functores definidas por
instance Functor [] where
fmap = map
Ejemplo de evaluación de fmap en listas
ghci> fmap (+3) [2,4,6]
[5,7,9]
ghci> fmap (+3) []
[]
ghci> (+3) <$> [2,4,6]
[5,7,9]
ghci> (+3) <$> []
[]
Las funciones son functores definidos por
instance Functor ((->) r) where
fmap f g = f . g
Ejemplo de evaluación de fmap con funciones
ghci> (fmap (+3) (+2)) 10
15
ghci> ((+3) <$> (+2)) 10
15
Los functores aplicativos aplican funciones en contextos a valores en contextos.
Los functores aplicativos está definidos en Control.Applicative por
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Definición
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
_ <*> Nothing = Nothing
Just f <*> Just x = Just (f x)
Ejemplos
ghci> (Just (+3)) <*> Just 2
Just 5
ghci> (Just (+3)) <*> Nothing
Nothing
ghci> Nothing <*> Just 2
Nothing
ghci> (Just (+3)) <*> pure 2
Just 5
Definición
instance Applicative [] where
pure a = [a]
[] <*> _ = []
(f:fs) <*> as = (map f as) ++ (fs <*> as)
Ejemplos
ghci> [(+3)] <*> [2]
[5]
ghci> [(+3)] <*> [2,4]
[5,7]
ghci> [(*10),(+2)] <*> [1,2,3]
[10,20,30,3,4,5]
Se puede aplicar una operación binaria a argumentos en contextos
ghci> (+) <$> (Just 2) <*> (Just 3)
Just 5
El resultado anterior se puede conseguir con liftA2:
ghci> liftA2 (+) (Just 2) (Just 3)
Just 5
Ejemplo de aritmética no determinista:
ghci> (*) <$> [4,5] <*> [2]
[8,10]
ghci> (+) <$> ((*) <$> [4,5] <*> [2]) <*> [6,1]
[14,9,16,11]
ghci> liftA2 (*) [4,5] [2]
[8,10]
ghci> liftA2 (+) (liftA2 (*) [4,5] [2]) [6,1]
[14,9,16,11]
ghci> let (.+) = liftA2 (+) :: [Int] -> [Int] -> [Int]
ghci> let (.*) = liftA2 (*) :: [Int] -> [Int] -> [Int]
ghci> [4,5] .* [2]
[8,10]
ghci> ([4,5] .* [2]) .+ [6,1]
[14,9,16,11]
Definición
instance Functor ((->) e) where
fmap = (.)
instance Applicative ((->) e) where
pure = const
f <*> x = \e -> (f e) (x e)
Se definen
type Nombre = String
data Empleado = Empleado { nombre :: Nombre
, telefono :: String }
deriving Show
data Datos = D { dNombre :: Nombre
, dSueldo :: Integer
, dTelefono :: String
, dEdad :: Int
}
dEmp :: Datos -> Empleado
dEmp = Empleado <$> dNombre <*> dTelefono
Ejemplos de tipos
ghci> :t Empleado
Empleado :: Nombre -> String -> Empleado
ghci> :t dNombre
dNombre :: Datos -> Nombre
ghci> :t dTelefono
dTelefono :: Datos -> String
Ejemplo de evaluación
ghci> dEmp (D "Juan" 60000 "954235498" 43)
Empleado {nombre = "Juan", telefono = "954235498"}
Las mónadas aplican funciones que devuelven valores en contextos a valores en contextos.
El operador de las mónadas que hace eso es >>=.
Mónada es la clase de tipos en las que está definido el operador >>= (y otros):
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
...
Maybe es un mónada definida por
instance Monad Maybe where
Nothing >>= func = Nothing
Just val >>= func = func val
Se define la función
mitad x | even x = Just (x `div` 2)
| otherwise = Nothing
Ejemplos de evaluación monádica
ghci> Just 6 >>= mitad
Just 3
ghci> Just 5 >>= mitad
Nothing
ghci> Nothing >>= mitad
Nothing
ghci> Just 12 >>= mitad
Just 6
ghci> Just 12 >>= mitad >>= mitad
Just 3
ghci> Just 12 >>= mitad >>= mitad >>= mitad
Nothing
Funciones de E/S
ghci> :t getLine
getLine :: IO String
ghci> :t readFile
readFile :: FilePath -> IO String
ghci> :t putStrLn
putStrLn :: String -> IO ()
Ejemplo
ghci> getLine >>= readFile >>= putStrLn
z.txt
Probando mónadas.
Fin.