<commit_before>Problema
--------

Si tenemos la multiplicacion (\*) definida para tanto Int como Float, luego

`square x = x*x`

debería transformarse en tiempo de compilación en dos funciones distintas

square (para ints) square (para floats)

Lo cual crece exponencialmente, por ejemplo con funciones como

`squares (x,y,z) = (x*x, y*y, z*z)`

que sería traducida en 8 funciones distintas.

Typeclasses al rescate
----------------------

Las typeclasses son un contrato o tipo de datos abstracto que agrupa las funciones sobrecargadas: es decir, definen una lista de funciones que un tipo deber implementar para considerarse de esa clase. Ejemplo: la typeclass Num dice que todos aquellos tipos que sean Num (Int o Float por ejemplo) van a definir las funciones (+) y (\*) y de que tipos son.

Las typeclasses tienen como primer consecuencia que funciones como squares, que tenía 8 tipos posibles, tenga uno solo:

`squares :: Num a, Num b, Num c => (a,b,c) -> (a,b,c)`

Donde Num es un typeclass.

Finalmente comenta como las typeclasses se pueden traducir/reescribir a un lenguaje sin typeclasses. Y por lo tanto, como pueden reutilizarse los mecanismos de inferencia de tipos de uno para el otro.

Y para esta traducción, usan la metáfora de un method dictionary. Cada tipo va a tener un diccionario con sus funciones sobrecargadas. Luego, cada función con \*polimorfismo parametrico\*, recibe como parámetro el method dictionary y usa la función adecuada:

Ejemplo:

`square x = x * x`

se transforma en algo como

`--ambos diccionarios son del mismo tipo (que es el tipo definido en la typeclass ;) )`
`dictInt = ...`
`dictFloat = ....`

`multi dict = dict !! 1 -- suponiendo que la función multiplicación esta en el diccionario en la posición 1`
`square dict x = multi dict x x`

Y cuando ejecutamos

`square 3`

se traduce, como 3 es un Int, en algo como

`square dictInt 3 `

En resumen: chequeo estático, dispatch dinámico :P (o algo dinámico)<commit_msg>Revision without comments imported from MediaWiki<commit_after>Problema
--------

Si tenemos la multiplicacion (\*) definida para tanto Int como Float, luego

`square x = x*x`

debería transformarse en tiempo de compilación en dos funciones distintas

square (para ints) square (para floats)

Lo cual crece exponencialmente, por ejemplo con funciones como

`squares (x,y,z) = (x*x, y*y, z*z)`

que sería traducida en 8 funciones distintas.

Typeclasses al rescate
----------------------

Las typeclasses son un contrato o tipo de datos abstracto que agrupa las funciones sobrecargadas: es decir, definen una lista de funciones que un tipo deber implementar para considerarse de esa clase. Ejemplo: la typeclass Num dice que todos aquellos tipos que sean Num (Int o Float por ejemplo) van a definir las funciones (+) y (\*) y de que tipos son.

Las typeclasses tienen como primer consecuencia que funciones como squares, que tenía 8 tipos posibles, tenga uno solo:

`squares :: Num a, Num b, Num c => (a,b,c) -> (a,b,c)`

Donde Num es un typeclass.

Finalmente comenta como las typeclasses se pueden traducir/reescribir a un lenguaje sin typeclasses. Y por lo tanto, como pueden reutilizarse los mecanismos de inferencia de tipos de uno para el otro.

Y para esta traducción, usan la metáfora de un method dictionary. Cada tipo va a tener un diccionario con sus funciones sobrecargadas. Luego, cada función con \*polimorfismo parametrico\*, recibe como parámetro el method dictionary y usa la función adecuada:

Ejemplo:

`square x = x * x`

se transforma en algo como

`--ambos diccionarios son del mismo tipo (que es el tipo definido en la typeclass ;) )`
`dictInt = ...`
`dictFloat = ....`

`multi dict = dict !! 1 -- suponiendo que la función multiplicación esta en el diccionario en la posición 1`
`square dict x = multi dict x x`

Y cuando ejecutamos

`square 3`

se traduce, como 3 es un Int, en algo como

`square dictInt 3 `

En resumen: chequeo estático, dispatch dinámico :P (o algo dinámico, hay magia en el medio a nivel compilador)

Más sobre Typeclasses en [Tipos de Haskell](tipos-de-haskell-typeclasses.html)
{'fraction_non_alphanumeric': 0.07995110024449878, 'fraction_numerical': 0.0034229828850855745, 'mean_word_length': 4.00122249388753, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3802638', 'n_tokens_mistral': 1494, 'n_tokens_neox': 1455, 'n_words': 609}