Różnica między TypeClasses [Haskell] i Traits [Rust]

0

Czytam o Ruscie i im dłużej czytam tym bardziej się zastanawiam czy Traity z Rusta czymś się różnią od TypeClass z Haskella. Rust oczywiście nie pozwala na polimorfizm czasu wykonania o ile obiekt/wartość jest na stosie a nie na stercie, ale oprócz tego różnic nie widzę.

Czy to tylko chwyt marketingowy? Tak jak to żeby koprodukcję nazywać enumem. Czyli że niemainstreamowe konstrukcje nazywać nazwami mainstreamowymi, w nadziej że dzięki temu szybciej się przyjmą?

2

Przymykając oko na pewne szczegóły implementacyjne (np. na fakt, że aktualnie w Ruście, w porównaniu do Haskella, nie można utworzyć typów wyższego rzędu), obydwa mechanizmy pełnią tę samą funkcję: grupowanie typów względem ich zachowania.

Nie jestem pewien skąd wzięła się różnica w nazewnictwie - być może i chwyt marketingowy :-)

4

czy Traity z Rusta czymś się różnią od TypeClass z Haskella

Głównie możliwościami, ale jest to to samo podejście. Popatrz na https://doc.rust-lang.org/reference/influences.html

Influences
Rust is not a particularly original language, with design elements coming from a wide range of sources. Some of these are listed below:
Haskell (GHC): typeclasses, type families

Haskell ma bardziej rozbudowany system generycznych typów, Rust ma chyba bardziej nastawiony na optymalizacje czasu kompilacji (jak np gwarancja monomorfizacji czy wchodzące const generics).

Czy to tylko chwyt marketingowy? Tak jak to żeby koprodukcję nazywać enumem. Czyli że niemainstreamowe konstrukcje nazywać nazwami mainstreamowymi, w nadziej że dzięki temu szybciej się przyjmą?

Raczej nie chodzi o anty-mainstream tylko anty-OOP i anty-Java. trait do typeclassy średnio pasuje, ale class (używane w Haskellu dla typeclass) kojarzy się z OOP i Javą.

0

Wszystkie mechanizmy polimorfizmu będą do siebie podobne. Jak się zastanowisz to klasy w haskellu są analogiczne do interfejsów z innych języków.

Różnica jest głównie w poziomie zaawansowania systemu typów. Wiele pożytecznych konstruktów haskellowych nie ma prawa istnieć w ruście, bo ten ma uboższe typowanie.

1

Wszystkie mechanizmy polimorfizmu będą do siebie podobne. Jak się zastanowisz to klasy w haskellu są analogiczne do interfejsów z innych języków.

Między typeclass, a interfejsem znanym z OOP jest zasadnicza różnica: implementować interfejsy możesz tylko w miejscu deklaracji klasy, natomiast implementować typeclass dla typu T możesz zarówno w miejscu deklaracji typu T i w miejscu deklaracji typeclassy. Można mieć też https://wiki.haskell.org/Orphan_instance - w Scali to chyba dość częste.

3
part napisał(a):

Wszystkie mechanizmy polimorfizmu będą do siebie podobne. Jak się zastanowisz to klasy w haskellu są analogiczne do interfejsów z innych języków.

IMO type classy można uznać za uogólnienie interfejsów znanych z języków OOP. Interfejs pozwala na polimorfizm tylko dla klas i tylko dla argumentu "this", gdzie type klasy pozwalają na większą dowolność.

Fajnym przykładem jest typowa magia wymagana w językach używających zliczania referencji. Jeżeli chcemy mieć możliwość dobrania się do wskaźnika z poziomu typu niżej to wystarczy odpowiednio zmodyfikować sygnaturę:

struct Foo

impl Foo {
    fn foo(self: Rc<Self>) {
      do_something(self.clone());
    }
}

co jest eleganckie, bo naszym this może być też Rc<Self>, a nie Self.

W C++ ten problem rozwiązuje się dużo trudniej, musimy robić haksy z mixinami i dodatkowym trzymaniem stanu wewnątrz instancji:

struct Foo: std::enable_shared_from_this<Foo> 
{
    void foo () {
        do_something(this->shared_from_this());
    }
};

bo this musi mieć taki sam typ jak klasa

1 użytkowników online, w tym zalogowanych: 0, gości: 1