Rust'daki özellikler ile Haskell'deki typeclasses arasındaki fark nedir?


157

Rust'daki özellikler en azından Yüzeysel olarak Haskell'deki tipik örneklere benziyor , ancak insanların aralarında bazı farklılıklar olduğunu yazdıklarını gördüm. Bu farklılıkların tam olarak ne olduğunu merak ediyordum.


8
Rust hakkında fazla bir şey bilmiyorum. Ancak diğer dillerdeki benzer teknolojiler için yaygın tökezleme blokları daha yüksek türlerdir (örneğin, parametreler parametreli tiplere göre değişebilir, ancak parametreleriyle değil mi?) Ve dönüş tipi polimorfizmdir (örneğin, bir işlev sonucunda bir özellik tipi görünebilir, ancak herhangi bir yerde değil) argümanlarda?). Haskell'deki ilk örneği class Functor f where fmap :: (a -> b) -> (f a -> f b); ikincisinin bir örneği class Bounded a where maxBound :: a.
Daniel Wagner

4
GHC ayrıca çok parametreli tip sınıflarını (çeşitli türleri içeren özellikler) ve fonksiyonel bağımlılıkları da destekler, ancak bu resmi Haskell spesifikasyonunun bir parçası değildir. Bağlantınızda önerilen Rust sözdiziminden yola çıkarak, her seferinde yalnızca bir tür üzerinde değişen özellikleri destekleyebilir, ancak bu karar yine derin deneyime dayanmaz.
Daniel Wagner

4
@DanielWagner Dönüş tipi polimorfizm vardır (örn. std::default) Ve çok parametreli özellikler bir çeşit çalışma (işlevsel bağımlılıkların bir analogu dahil) olsa da, AFAIK'in ayrıcalıklı ilk parametrenin etrafında çalışması gerekir. Ancak HKT yok. Onlar uzak gelecek dilek listesinde ama henüz ufukta değiller.

4
diğer bir fark, yetim vakalarının tedavisidir. Rust, bir özellik için yeni bir implenin nerede yazılabileceği konusunda daha sıkı tutarlılık kurallarına sahip olmaya çalışır. Daha fazla ayrıntı için bu tartışmaya bakın (özellikle burada )
Paolo Falabella

1
Rust, Haskell'in tip aileleri kadar güçlü olmasa da, şimdi ilişkili türleri ve eşitlik kısıtlamalarını desteklemektedir . Ayrıca özellik nesneleri aracılığıyla varoluşçu tiplere sahiptir .
Lambda Fairy

Yanıtlar:


61

Temel düzeyde, çok fazla fark yok, ama hala oradalar.

Haskell, tıpkı özellikler içerdikleri nesnelerdeki OOP yöntemlerini tanımladığı gibi, bir tip sınıfında tanımlanan işlevleri veya değerleri 'yöntemler' olarak tanımlar. Bununla birlikte, Haskell bunlarla farklı şekilde ilgilenir, onlara OOP gibi bir nesneye sabitlemek yerine bireysel değerler olarak davranır. Bu, en belirgin yüzey seviyesi farkı ile ilgilidir.

Rust'un bir süre yapamayacağı tek şey , rezil ve tipik sınıflar gibi daha üst düzey tip özelliklerdi .FunctorMonad

Bu, Rust özelliklerinin genellikle 'somut tip' olarak adlandırılan şeyi, başka bir deyişle, genel bir argüman olmadan tanımlayabileceği anlamına gelir. Başlangıçtan itibaren Haskell, üst düzey işlevlerin diğer işlevleri nasıl kullandığına benzer türler kullanan daha üst düzey tipler yapabilir: birini diğerini tanımlamak için kullanma. Bir süre için bu Rust'da mümkün değildi, ancak ilişkili öğeler uygulandığından, bu tür özellikler yaygın ve deyimsel hale geldi.

Dolayısıyla, uzantıları görmezden gelirsek, bunlar tam olarak aynı değildir, ancak her biri diğerinin neler yapabileceğini yaklaşık olarak tahmin edebilir.

Yorumlarda da belirtildiği gibi, GHC'nin (Haskell'in ana derleyicisi), çok parametreli (yani birçok tür dahil) daktilolar ve tip bağımlılıklarına izin veren hoş bir seçenek de dahil olmak üzere, tipik sınıflar için diğer seçenekleri desteklediği de belirtilmelidir. ve tip ailelere götürür . Bildiğim kadarıyla, Rust gelecekte ne de olsa eğlenceliDeps veya tip aileleri yok. †

Sonuç olarak, özellikler ve tipik sınıflar, etkileşim biçimleri nedeniyle, hareket etmelerini ve sonunda oldukça benzer görünmelerini sağlayan temel farklılıklara sahiptir.


† Haskell'in tip sınıfları hakkında güzel bir makale (daha yüksek tipler de dahil olmak üzere) burada bulunabilir ve özelliklerle ilgili Örnek bölümüyle Rust'ı burada bulabilirsiniz.


1
Rust hala daha yüksek tür çeşitlerine sahip değildir. "Kötü şöhretli" bir gerekçe gerektirir. Functor inanılmaz derecede yaygın ve bir kavram olarak kullanışlıdır. Tür aileleri, ilişkili türlerle aynıdır. Fonksiyonel bağımlılıklar, ilişkili türlerle (Haskell dahil) esasen gereksizdir. Rust'un eksik olduğu şey. fundeps, tedbirsizlik ek açıklamalarıdır. Geriye doğru sahipsiniz, Rust'un özellikleri ve Haskell'in tip sınıfları yüzeyde farklıdır, ancak altına baktığınızda birçok fark buharlaşır.
Geriye

İlişkili öğeler artık birçok durumda idomatik olarak kabul ediliyor, değil mi?
Vaelus

@Vaelus Haklısınız — Bu yanıt biraz güncellenmelidir. Şimdi düzenleniyor.
AJFarmar

19

Bence mevcut cevaplar Rust özellikleri ile Haskell tipi sınıflar arasındaki en temel farklılıkları görmezden geliyor. Bu farklılıklar, özelliklerin nesne yönelimli dil yapılarıyla ilişkilendirilme şekliyle ilgilidir. Bununla ilgili bilgi için Rust kitabına bakınız .

  1. Özellik bildirimi bir özellik türü oluşturur . Bu, böyle bir türün (veya daha doğrusu türün referanslarının) değişkenlerini bildirebileceğiniz anlamına gelir. Özellik türlerini işlev, yapı alanları ve tür parametresi örneklerinde parametre olarak da kullanabilirsiniz.

    Bir sürekli başvuru değişkeni, çalışma zamanında başvurulan nesnenin çalışma zamanı türü özelliği uyguladığı sürece farklı türdeki nesneleri içerebilir.

    // The shape variable might contain a Square or a Circle, 
    // we don't know until runtime
    let shape: &Shape = get_unknown_shape();
    
    // Might contain different kinds of shapes at the same time
    let shapes: Vec<&Shape> = get_shapes();

    Tür sınıfları bu şekilde çalışmaz. Tür sınıfları tür oluşturmaz , bu nedenle sınıf adıyla değişken bildiremezsiniz. Tür sınıfları , tür parametreleri üzerinde sınır görevi görür , ancak tür parametreleri tür sınıfının kendisi ile değil somut bir türle başlatılmalıdır.

    Aynı tür sınıfını uygulayan farklı türde farklı şeylerin bir listesi olamaz. (Bunun yerine, Haskell'de benzer bir şeyi ifade etmek için varoluşçu türler kullanılır.) Not 1

  2. Özellik yöntemleri dinamik olarak gönderilebilir . Bu, yukarıdaki bölümde açıklananlarla güçlü bir şekilde ilişkilidir.

    Dinamik gönderme, başvuru noktasından hangi yöntemin çağrıldığını belirlemek için bir başvuru noktası olan nesnenin çalışma zamanı türünün kullanıldığı anlamına gelir.

    let shape: &Shape = get_unknown_shape();
    
    // This calls a method, which might be Square.area or
    // Circle.area depending on the runtime type of shape
    print!("Area: {}", shape.area());

    Yine, bunun için Haskell'de varoluşçu türler kullanılır.

Sonuç olarak

Bana öyle geliyor ki, özellikler birçok açıdan tip sınıflarıyla aynı kavramdır. Ek olarak, nesne yönelimli arayüzlerin işlevselliğine sahiptirler.

Diğer yandan Haskell'in tip sınıfları daha ileridir. Haskell, örneğin çok parametreli tip sınıfları gibi daha yüksek türlü tiplere ve uzantılara sahiptir.


Not 1 : Rust'un son sürümlerinde, özellik adlarının tür olarak kullanımını ve özellik adlarının sınır olarak kullanımını ayırt etmek için bir güncelleme vardır. Bir özellik türünde, adın başına dynanahtar kelime gelir. Daha fazla bilgi için örneğin bu cevaba bakınız .


2
"Tür sınıfları tür oluşturmaz" - Bence dyn Traitözellikleri / tür sınıfları ile ilgili varoluşsal yazım biçimi olarak anlamak en iyisidir . dynBir operatörü, onları türlere yansıtan sınırlar üzerinde düşünebiliriz , yani dyn : List Bound -> Type. "Sınıf adıyla tanimlamanızda böylece" Haskell için ve ilgili bu fikrinden hareketle biz Haskell dolaylı yapabilirsiniz: data Dyn (c :: * -> Constraint) = forall (t :: Type). c t => D t. Bunu tanımladıktan sonra çalışabiliriz [D True, D "abc", D 42] :: [D Show].
Centril

8

Rust'un “özellikleri” Haskell'in tip sınıflarına benzer.

Haskell ile temel fark, özelliklerin yalnızca nokta gösterimine sahip ifadelere, yani a.foo (b) formuna müdahale etmesidir.

Haskell tipi sınıflar daha üst düzey tiplere uzanır. Rust özellikleri yalnızca yüksek sıra türlerini desteklemez, çünkü tüm dilde eksiktirler, yani özellikler ve tip sınıfları arasında felsefi bir fark değildir


1
Rust'daki özellikler "yalnızca nokta gösterimine sahip ifadelere müdahale etmez". Örneğin, Defaultyöntemi olmayan özelliği, yalnızca yöntemle ilişkili olmayan işlevleri düşünün .
0:23
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.