На базовому рівні різниці немає, але вони все ще є.
Haskell описує функції або значення, визначені в класному класі, як "методи", подібно до того, як ознаки описують методи OOP в об'єктах, до яких вони додаються. Однак Хаскелл має справу з цим по-різному, трактуючи їх як індивідуальні цінності, а не прив’язуючи їх до об'єкта, як OOP призведе до цього. Йдеться про найбільш очевидну різницю на рівні поверхні.
Єдине, що Руст не міг зробити деякий час, - це риси , що набирають вищого порядку , такі як сумнозвісні Functor
та Monad
класні типи.
Це означає, що риси Іржі могли описувати лише те, що часто називають "конкретним типом", іншими словами, без загального аргументу. Haskell з самого початку міг створювати типи класів вищого порядку, які використовують типи, аналогічні тому, як функції вищого порядку використовують інші функції: використовуючи одну для опису іншої. Протягом певного періоду це не було можливим у Іржі, але з тих пір, коли пов'язані елементи були реалізовані, такі риси стали звичними та ідіоматичними.
Тож якщо ми ігноруємо розширення, вони не зовсім однакові, але кожне може наблизити те, що може зробити інший.
Як зазначається в коментарях, також зазначається, що GHC (головний компілятор Haskell) підтримує подальші параметри для класів типів, включаючи багатопараметричні (тобто багато типів, що беруть участь) типи класів і функціональні залежності , чудовий варіант, що дозволяє проводити обчислення на рівні типу , і веде до типу сімей . Наскільки мені відомо, у Rust немає ні сімейства funDeps, ні типів, хоча це може бути в майбутньому. †
Загалом, риси та класи класів мають принципові відмінності, які завдяки способу їх взаємодії змушують їх діяти і, зрештою, виглядають досить схожими.
† Приємну статтю про типові класи Хаскелла (включаючи вищі типи) можна знайти тут , а розділ Rust by Example про риси можна знайти тут
class Functor f where fmap :: (a -> b) -> (f a -> f b)
; прикладом останнього єclass Bounded a where maxBound :: a
.