Introducción: ¿por qué comparar Rust y Haskell?
\n\nSi alguna vez has mirado en Stack Overflow buscando una respuesta a la pregunta "What is the difference between traits in Rust and typeclasses in Haskell?", sabes que es un tema candente. Miles de visitas, decenas de votos: la comunidad de desarrolladores realmente quiere entender en qué se diferencian estos dos mecanismos.
\n\nA primera vista, se parecen como hermanos: tanto los traits en Rust como las typeclasses en Haskell permiten definir un comportamiento común para diferentes tipos. Pero si profundizas, descubres que la filosofía, implementación y aplicación práctica son universos distintos.
\n\nEn este artículo, analizaremos las diferencias clave con ejemplos reales de código en Rust (con algunas pinceladas de Haskell para contrastar), y al final tendrás una comprensión clara de: cuándo usar traits y dónde es mejor pensar en un enfoque similar a typeclass.
\n\nBreve resumen: ¿qué son los traits en Rust?
\n\nLos traits en Rust son una forma de declarar un conjunto de métodos que deben ser implementados para un tipo específico. Son la base de la programación genérica (generics) y del polimorfismo en Rust.
\n\nUn ejemplo simple: imagina que queremos que diferentes tipos puedan "saludar".
\n\ntrait Greeter {\n fn greet(&self) -> String;\n}\n\nstruct Person {\n name: String,\n}\n\nimpl Greeter for Person {\n fn greet(&self) -> String {\n format!("¡Hola, me llamo {}!", self.name)\n }\n}\n\nstruct Robot {\n model: String,\n}\n\nimpl Greeter for Robot {\n fn greet(&self) -> String {\n format!("Bip-bop, modelo: {}", self.model)\n }\n}\n\nfn say_hello(item: &impl Greeter) {\n println!("{}", item.greet());\n}\n\nfn main() {\n let person = Person { name: "Ana".into() };\n let robot = Robot { model: "R2-D2".into() };\n say_hello(&person);\n say_hello(&robot);\n}\n\nAquí, Greeter es un trait. Los tipos Person y Robot lo implementan a su manera. La función say_hello acepta cualquier tipo que implemente Greeter. Esto es polimorfismo a través de traits.
Breve resumen: ¿qué son las typeclasses en Haskell?
\n\nUna typeclass en Haskell es una interfaz que define un conjunto de funciones que pueden ser implementadas para diferentes tipos. Suena familiar, ¿verdad?
\n\nAsí se vería un ejemplo similar en Haskell:
\n\nclass Greeter a where\n greet :: a -> String\n\ndata Person = Person { name :: String }\ndata Robot = Robot { model :: String }\n\ninstance Greeter Person where\n greet (Person n) = "¡Hola, me llamo " ++ n ++ "!"\n\ninstance Greeter Robot where\n greet (Robot m) = "Bip-bop, modelo: " ++ m\n\nsayHello :: Greeter a => a -> IO ()\nsayHello item = putStrLn (greet item)\n\nmain = do\n sayHello (Person "Ana")\n sayHello (Robot "R2-D2")\n\nLa sintaxis es diferente, pero la lógica es la misma. Y sin embargo, las diferencias entre traits en Rust y typeclasses en Haskell comienzan precisamente aquí.
\n\nDiferencia clave n.º 1: Monomorfización vs boxing (Box)
\n\nLa diferencia más fundamental entre traits y typeclasses radica en cómo el compilador maneja el código genérico.
\n\nRust: monomorfización
\n\nCuando escribes fn say_hello(item: &impl Greeter), el compilador de Rust crea una copia separada de la función para cada tipo concreto. Esto se llama monomorfización. Resultado: abstracción de costo cero (zero-cost abstraction): no pagas por lo que no usas. Pero el tamaño del código puede aumentar.
Haskell: boxing (por defecto)
\n\nEn Haskell, las typeclasses generalmente se implementan mediante diccionarios de métodos (vtable). El compilador pasa un parámetro implícito: una tabla con punteros a funciones. Esto se llama boxing. Pagas por la