Funtores, Aplicativos y Mónadas en imágenes

El link original al artículo es:

http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

Funtores, Aplicativos y Mónadas en imágenes

data Maybe a = Nothing | Just a

Funtores

> fmap (+3) (Just 2)
Just 5
La magia pasa ahí
class Functor f where
fmap :: (a->b) -> fa -> fb

1. Para hacer ‘f’ un Funtor,
2. Ese tipo de datos tiene que definir cómo `fmap` se va a comportar para él

fmap :: (a->b) -> fa -> fb

1. `fmap` toma una función, como (+3)
2. y un funtor, como `Just 2`
3. y devuelve otro Funtor, como `Just 5`

> fmap (+3) (Just 2)
Just 5
instance Functor Maybe where
fmap func (Just val) = Just (func val)
fmap func Nothing = Nothing
fmap (+3) (Just 2)

1. Desenvuelve/extrae el valor de su contexto
2. Aplica la función
3. Vuelve a envolver el resultado en un contexto igual al inicial

1. No hay valor
2. No apliques la función
3. Acabas teniendo nada

> fmap (+3) Nothing
Nothing
Bill O’Really que ignora totalmente el funtor Maybe
post = Post.find_by_id(1)
if post
return post.title
else
return nil
end
fmap (getPostTitle) (findPost 1)
getPostTitle <$> (findPost 1)

1. Un array de valores

2. Aplica la función a cada valor

3. Un nuevo array de valores

instance Functor [] where
fmap = map
fmap (+3) (+1)

- Toma un valor
- Devuelve un valor

- Toma un valor
- Devuelve un valor

> import Control.Applicative
> let foo = fmap (+3) (+2)
> foo 10
15
instance Functor ((->) r) where
fmap f g = f . g

Aplicativos

1. Una función envuelta en un contexto
2. Un valor en un contexto
3. Desenvuelve tanto el valor como la función y aplícasela al valor
4. Envuelvelo en un conexto otra vez.

Just (+3) <*> Just 2 == Just 5
> [(*2), (+3)] <*> [1, 2, 3]
[2, 4, 6, 4, 5, 6]
> (+) <$> (Just 5)
Just (+5)
> Just (+5) <$> (Just 4)
ERROR ??? QUÉ QUIERE DECIR??? POR QUÉ ESTÁ LA FUNCIÓN ENVUELTA EN UN JUST?
> (+) <$> (Just 5)
Just (+5)
> Just (+5) <*> (Just 3)
Just 8
“Los chicos mayores usan funciones con cualquier número de argumentos”, 
“Armado con `<$>` y `<*>`, puedo coger cualquier función que espere cualquier número de argumentos desenvueltos. Luego le paso todos los argumentos envueltos y obtengo un valor envuelto! ¡JAJAJAJAJAJAJAJA!”
> (*) <$> Just 5 <*> Just 3
Just 15
> liftA2 (*) (Just 5) (Just 3)
Just 15

Mónadas

Solamente una Mónada a su bola
half x = if even x
then Just (x `div` 2)
else Nothing

- Toma un valor
- Devuelve un valor envuelto

half quejándose al recibir un valor envuelto
> Just 3 >>= half
Nothing
> Just 4 >>= half
Just 2
> Nothing >>= half
Nothing
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b

1. >>= recibe una Mónada, como (Just 3)
2. Y una función que devuelve una Mónada (como la función `half`)
3. Y devuelve una Mónada

instance Monad Maybe where
Nothing >>= func = Nothing
Just val >>= func = func val

1. Bind desenvuelve el valor
2. Le pasa ese valor a la función
3. Devuelve un valor envuelto (ya sea un `Just` o un `Nothing`)

1. Nada entra
2. No se hace nada
3. Nada sale

> Just 20 >>= half >>= half >>= half
Nothing
getLine :: IO String
readFile :: FilePath -> IO String
putStrLn :: String -> IO ()

1. Lee los datos del usuario
2. Usalos para leer un fichero
3. ¡Imprime el contenido del fichero!

getLine >>= readFile >>= putStrLn

foo = do
filename <- getLine
contents <- readFile filename
putStrLn contents

Conclusión

- Funtor
- Aplicativo
- Mónada

--

--

Software Engineer

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store