34
Telefónica Digital – Video Products Definition & Strategy using std::cpp 2014 Joaquín Mª López Muñoz <[email protected]> Madrid, octubre 2014 Por fin entiendo qué son las mónadas

Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Telefónica Digital – Video Products Definition & Strategy

using std::cpp 2014

Joaquín Mª López Muñoz <[email protected]> Madrid, octubre 2014

Por fin entiendo qué son las mónadas

Page 2: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

No es esto…

Page 3: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Tampoco esto…

Page 4: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

¡Son las mónadas!

Page 5: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Definición formal

Page 6: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Definición formal

Page 7: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Pero, ¿qué es realmente una mónada?

Una cinta transportadora

Un overload del operador “;”

Una unidad de computación

Un truco para introducir efectos

laterales en programación

funcional

Un objeto cuyos métodos

devuelven mónadas

No es posible definir qué es una mónada

Algo parecido a un escritorio

Una forma de componer funciones

Page 8: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Construyamos una mónada en C++

Page 9: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

optional<T>

template<typename T> struct optional { optional(T const& x) optional(none_t); T const& get()const; T& get(); operator bool()const; // not really }; optional<double> inv(double x){ if(x==0.0)return none; else return 1.0/x; } optional<double> sqr(double x){ if(x<0.0)return none; else return std::sqrt(x); } optional<double> arcsin(double x){ if(x<-1.0||x>1.0)return none; else return std::asin(x); }

Page 10: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Calcular…

La composición directa de funciones no compila optional<double> f(double x) { return inv(arcsin(sqr(x)); } main.cpp: In function 'boost::optional<double> f(double)': main.cpp:34:27: error: cannot convert 'boost::optional<double>' to 'double' for argument '1' to 'boost::optional<double> arcsin(double)' return inv(arcsin(sqr(x)); ^

arcsin acepta doubles, no optional<double>s

Semántica deseada: none_t aborta la computación

𝒇 𝒙 =𝟏

arcsin( 𝒙)

Page 11: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Ahora sí

optional<double> f(double x) { auto y=sqr(x); auto z=y?arcsin(y.get()):none; auto w=z?inv(z.get()):none; return w; }

¿Detectas un patrón aquí?

Page 12: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Hagámoslo genérico

template<typename T,typename F> auto operator>>=(const optional<T>& x,F&& f) { return x?f(x.get()):none; } optional<double> f(double x) { return (sqr(x)>>=arcsin)>>=inv; }

No hay nada especial en la elección de “>>=”

En C++, de hecho, no es muy buena elección

Léase bind (tampoco muy afortunado en C++)

Page 13: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

optional<double> f(double x) { return inv(arcsin(sqr(x)); } optional<double> f(double x) { return (sqr(x)>>=arcsin)>>=inv; }

>>= es un adaptador activo

x arcsin inv

>>= sqr x

arcsin

>>=

inv

sqr

Page 14: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

optional<double> f(double x) { return ((optional<double>(x)>>=sqr)>>=arcsin)>>=inv; }

unit acepta un objeto x y devuelve la mónada asociada a x

También se lo llama return (confuso en C++)

En este ejemplo unit(x) ~ optional<double>(x)

Un poco de Lego

>>= x

arcsin

>>=

inv

>>=

sqr

unit

Page 15: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

optional<double> f(double x) { auto g=[](double y){return arcsin(y)>>=inv;}; return sqr(x)>>=g; }

bind es “asociativo”

Un poco de Lego

>>= sqr x

arcsin

inv

>>=

Page 16: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

optional<double> f(double x) { auto minv=[](const optional<double>& y){return y>>=inv;}; auto marcsin=[](const optional<double>& y){return y>>=arcsin;}; auto msqr=[](const optional<double>& y){return y>>=sqr;}; return minv(marcsin(msqr(optional<double>(x)))); }

Por cierto, esta mónada es comúnmente conocida como Maybe Monad

Un poco de Lego

sqr

>>=

arcsin

>>=

inv

>>=

x unit

Page 17: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Las leyes de la mónada

unit : T M<T>

>>= : (M<T>, T M<T’>) M<T’>

unit(x) >>= f ≡ f(x)

m >>= unit ≡ m

(m >>= f) >>= g ≡ m >>= λx.(f(x) >>= g)

Page 18: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

¿Qué es una mónada? Mi modesto intento de definición

Page 19: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Una mónada es un patrón de diseño que permite componer funciones con tipos de retorno extendidos

Un tipo extendido contiene 0 ó más valores de un tipo básico más cierta semántica/información asociada

¿Qué es una mónada? Mi modesto intento de definición

Page 20: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

template<typename T> class histogram { public: histogram(){} histogram(const T& x); // our unit ctor, later on const_iterator begin()const; const_iterator end()const; void add(const T& x,double f); }; histogram<int> dice(int n) { histogram<int> res; for(int i=1;i<=n;++i)res.add(i,1.0/n); return res; } int main() { std::cout<<dice(6); }

Algo más complicado: histogramas

1 ******************** 2 ******************** 3 ******************** 4 ******************** 5 ******************** 6 ********************

Page 21: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Composición de histogramas ~ probabilidad condicionada

1

0.2

2

0.4

3

0.4

A

0.2

B

0.3

C

0.5

A

0.0

B

0.6

C

0.4

A

0.25

B

0.5

C

0.25

A

0.14

B

0.5

C

0.36

Page 22: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

template<typename T,typename F> auto operator>>=(const histogram<T>& x,F&& f) { decltype(f(x.begin()->first)) res; for(const auto& p:x){ for(const auto& q:f(p.first)){ res.add(q.first,q.second*p.second); } } return res; } int main() { auto h=dice(6)>>=dice; std::cout<<h; }

Estrictamente hablando, histogram<T> es una mónada

restringida

Composición de histogramas ~ >>=

1 ************************************************* 2 **************************** 3 ******************* 4 ************ 5 ******* 6 ***

Page 23: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

int main() { auto h1=dice(6); auto h2=dice(4); auto h3= h1>>=[&](int x){ return h2>>=[&](int y){ return histogram<int>(x+y); }; }; std::cout<<h3; }

En Haskell, este constructo se implementa con la notación do do x <- dice 6 y <- dice 4 return x+y

No tan relevante en un lenguaje imperativo como C++ (por ahora)

Pero hay otro concepto más interesante aquí…

Suma de experimentos

2 ***** 3 ********** 4 *************** 5 ******************** 6 ******************** 7 ******************** 8 *************** 9 ********** 10 *****

Page 24: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Lifting monádico

Page 25: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

f(T1, … ,Tn) R F(M<T1>, … , M<Tn>) M<R> template<template<typename> class M,typename T1,typename T2> auto operator+(const M<T1>& m1,const M<T2>& m2) { return m1>>=[&](const T1& x){ return m2>>=[&](const T2& y){ return M<decltype(x+y)>(x+y); }; }; } int main() { auto h1=dice(6); auto h2=dice(4); auto h3=h1+h2; std::cout<<h3; std::cout<<"--------------------------\n"; std::cout<<optional<int>(4)+optional<int>(3)<<"\n"; std::cout<<optional<int>(4)+optional<int>(none)<<"\n"; }

Lifting monádico

2 ***** 3 ********** 4 *************** 5 ******************** 6 ******************** 7 ******************** 8 *************** 9 ********** 10 ***** -------------------------- 7 none

Page 26: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Intersección de líneas captura / closure

Lifting monádico con argumentos variádicos: http://tinyurl.com/mlifting

La implementación no es trivial

Diagrama de flujo

>>=

+ unit

m2

>>= m1

Page 27: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Un catálogo de mónadas

Page 28: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Un catálogo de mónadas

Maybe

List

I/O

State

Reader

Writer

Continuation

Page 29: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Continuation Monad (muy por encima)

Page 30: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Construcción de un hilo

template<typename T,typename R> struct yarn { yarn(const T& x); template<typename F> // F: T->T2 yarn<T2,R> then(F f)const; R run(); }; int str_size(const std::string& str); int times_10(int x); std::string to_str (int x); int main() { auto c1=yarn<std::string,int>("hello"). then(str_size). then(times_10). then(to_str). then(str_size); std::cout<<"running...\n"; std::cout<<c1.run()<<"\n"; }

Page 31: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

str_size, times_10, to_str no devuelven valores monádicos

De hecho, then se implementa en función de >>=

¿Tanto lío para llamar unas cuantas funciones una tras otra?

El esquema es familiar, ¿no?

then hello then then

times_10 str_size to_str

then

str_size

then >>=

f f

yarn

yarn

Page 32: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Unas notas antes de partir

Page 33: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Unas notas antes de partir

Es posible entender las mónadas

¡Veo mónadas por todas partes!

Patrón de diseño para la composición de funciones extendidas

Haskell: mónadas + do estilo imperativo

C++: inversión de control, entornos no imperativos

Lifting remplazamiento de valores básicos por valores monádicos

Louis, creo que esto puede ser el comienzo de una bella amistad

Page 34: Por fin entiendo qué son las mónadas - using std::cpp · Por fin entiendo qué son las mónadas . ... Por cierto, esta mónada es comúnmente conocida como Maybe Monad Un poco de

Por fin entiendo qué son las mónadas

Gracias

github.com/joaquintides/usingstdcpp2014

using std::cpp 2014

Joaquín Mª López Muñoz <[email protected]> Madrid, octubre 2014