Na podstawowym poziomie nie ma dużej różnicy, ale nadal istnieją.
Haskell opisuje funkcje lub wartości zdefiniowane w typeklasie jako „metody”, tak jak cechy opisują metody OOP w obiektach, które obejmują. Jednak Haskell traktuje je w inny sposób, traktując je jako indywidualne wartości, zamiast przypinać je do obiektu, jak prowadziłby OOP. Chodzi o najbardziej oczywistą różnicę w poziomach powierzchni.
Jedyną rzeczą, której Rust nie mógł zrobić przez jakiś czas, były cechy typizowane wyższego rzędu , takie jak niesławne Functor
iMonad
Jedyną typizowane typeklasy.
Oznacza to, że cechy Rusta mogą opisywać tylko to, co często nazywa się „typem konkretnym”, innymi słowy, bez argumentu ogólnego. Haskell od samego początku mógł tworzyć typeklasy wyższego rzędu, które używają typów podobnych do tego, jak funkcje wyższego rzędu używają innych funkcji: używając jednej do opisania drugiej. Przez pewien czas nie było to możliwe w Rust, ale od tego czasu zaimplementowano powiązane przedmioty , takie cechy stały się powszechne i idiomatyczne.
Więc jeśli zignorujemy rozszerzenia, nie są one dokładnie takie same, ale każde z nich może przybliżać, co może zrobić drugie.
Należy również wspomnieć, jak powiedziano w komentarzach, że GHC (główny kompilator Haskella) obsługuje dalsze opcje dla typeklas, w tym typeklasy wieloparametrowe (tj. Wiele typów) i zależności funkcjonalne , urocza opcja, która pozwala na obliczenia na poziomie typu i prowadzi do rodzin typów . O ile mi wiadomo, Rust nie ma ani funDeps, ani rodzin typów, chociaż może się to zdarzyć w przyszłości. †
Podsumowując, cechy i typeklasy mają fundamentalne różnice, które ze względu na sposób, w jaki wchodzą w interakcje, sprawiają, że zachowują się i ostatecznie wydają się dość podobne.
† Przyjemny artykuł o typeklasach Haskella (w tym o wyższych typach) można znaleźć tutaj , a rozdział Rust by Example dotyczący cech można znaleźć tutaj
class Functor f where fmap :: (a -> b) -> (f a -> f b)
; przykładem tego ostatniego jestclass Bounded a where maxBound :: a
.