Tip sınıfı - Type class

Gelen bilgisayar bilimleri , bir tür sınıf bir olan tip sistem desteklediği bu yapı geçici polimorfizmi . Bu, parametrik olarak polimorfik türlerdeki değişkenlere kısıtlamalar eklenerek elde edilir . Böyle bir kısıtlama tipik olarak bir tür sınıfını Tve bir tür değişkenini içerir ave bu a, yalnızca üyeleri ile ilişkili aşırı yüklenmiş işlemleri destekleyen bir türe somutlaştırılabilen anlamına gelir T.

Tip sınıfları ilk olarak Philip Wadler ve Stephen Blott tarafından Standard ML'deki "eqtypes"ın bir uzantısı olarak önerildikten sonra Haskell programlama dilinde uygulandı ve başlangıçta aşırı yüklenmiş aritmetik ve eşitlik operatörlerini ilkeli bir şekilde uygulamanın bir yolu olarak tasarlandı . Standart ML'nin "eqtypes" ının aksine, Haskell'de tür sınıflarının kullanımı yoluyla eşitlik operatörünün aşırı yüklenmesi, derleyici ön ucunda veya temeldeki tür sisteminde kapsamlı bir değişiklik gerektirmez .

Yaratılışlarından bu yana, tip sınıflarının birçok başka uygulaması keşfedilmiştir.

genel bakış

Tip sınıfları, sınıfa ait her tip için var olması gereken, ilgili tipleriyle birlikte bir dizi fonksiyon veya sabit isim belirterek tanımlanır. Haskell'de türler parametrelendirilebilir; Eqeşitliği kabul eden türleri içermesi amaçlanan bir tür sınıfı aşağıdaki şekilde bildirilir:

class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool

nerede asınıfının bir örneğidir Eqve aher biri 2 tür argüman alan ave bir boole döndüren 2 işlev (eşitlik ve eşitsizlik işlevleri) için işlev imzalarını tanımlar .

Tipi değişken aolan tür (olarak da bilinen son yılında GHC tür, yani serbest bırakılması) olduğunu TypeEq

Eq :: Type -> Constraint

Bildirim, " üzerinde tanımlanmış uygun türlerden ve adında işlevler varsa atür, tür sınıfına aittir " şeklinde okunabilir . Bir programcı daha sonra (bir öğenin listede olup olmadığını belirleyen) bir işlevi aşağıdaki şekilde tanımlayabilir : Eq(==)(/=)elem

elem :: Eq a => a -> [a] -> Bool
elem y []     = False
elem y (x:xs) = (x == y) || elem y xs

İşlev elem, tür sınıfına ait olanlara kadar değişebilen türleri sınırlayan a -> [a] -> Boolbağlamlı Eq atüre sahiptir . ( Not : Haskell 'sınıf kısıtlaması' olarak adlandırılabilir.) aaEq =>

Bir programcı , belirli bir tür için tüm yöntemlerin uygulamalarını tanımlayan bir örnek bildirimi kullanarak herhangi bir türü tbelirli bir tür sınıfının üyesi yapabilir . Örneğin, bir programcı yeni bir veri türü tanımlarsa , uygun gördükleri şekilde tür değerleri üzerinde bir eşitlik işlevi sağlayarak bu yeni türün bir örneğini yapabilirler . Bunu yaptıktan sonra, on işlevini , yani türdeki öğelerin listelerini kullanabilirler . CCttEqtelem[t]t

Tip sınıflarının, nesne yönelimli programlama dillerindeki sınıflardan farklı olduğunu unutmayın . Özel olarak, Eqbir tür değildir: diye bir şey yoktur değeri Çeşidi Eq.

Tip sınıfları, parametrik polimorfizm ile yakından ilişkilidir. Örneğin , tür sınıfı kısıtlaması " " elemolmasaydı, yukarıda belirtilen türünün parametrik olarak polimorfik tür olacağına dikkat edin . a -> [a] -> BoolEq a =>

Daha yüksek türde polimorfizm

A tipi sınıfı bir tür değişkeni almak gerekmez tür Type ama her türlü birini alabilir. Daha yüksek türlere sahip bu tür sınıflarına bazen yapıcı sınıflar denir (belirtilen yapıcılar, gibi Maybeveri oluşturucuları yerine, gibi tür oluşturuculardır Just). Bir örnek Monadsınıftır:

class Monad m where
  return :: a -> m a
  (>>=)  :: m a -> (a -> m b) -> m b

m'nin bir tür değişkenine uygulanması, tür değişkenine sahip olduğunu gösterir Type -> Type, yani bir tür alır ve bir tür döndürür, tür Monadşöyledir:

Monad :: (Type -> Type) -> Constraint

Çok parametreli tür sınıfları

Tür sınıfları, birden çok tür parametresine izin verir ve bu nedenle tür sınıfları, türler üzerindeki ilişkiler olarak görülebilir. Örneğin, GHC standart kitaplığında sınıf IArray, genel bir değişmez dizi arabirimini ifade eder. Bu sınıfta, tür sınıfı kısıtlaması , tür öğelerini içeren bir dizi türü olduğu IArray a eanlamına gelir . (Polimorfizm üzerindeki bu kısıtlama, örneğin kutusuz dizi türlerini uygulamak için kullanılır .) ae

Gibi multimethods , çok parametreli tipi sınıfları, birden fazla bağımsız değişken tiplerine bağlı olarak bir yöntemin farklı uygulamalarını çağrı, ve gerçekten de dönüş türleri destekler. Çok parametreli tür sınıfları, çalışma zamanında her çağrıda çağrılacak yöntemin aranmasını gerektirmez; bunun yerine çağrılacak yöntem, tek parametreli tür sınıflarında olduğu gibi, ilk olarak tür sınıfı örneğinin sözlüğünde derlenir ve saklanır.

Bu özellik Haskell 98 standardının bir parçası olmadığından, çok parametreli tür sınıflarını kullanan Haskell kodu taşınabilir değildir. Popüler Haskell uygulamaları, GHC ve Hugs , çok parametreli tür sınıflarını destekler.

Fonksiyonel bağımlılıklar

Haskell'de, programcının tür parametreleri arasında işlevsel bağımlılıklar bildirmesine olanak sağlamak için tür sınıfları iyileştirildi - ilişkisel veritabanı teorisinden ilham alan bir kavram . Yani programcı, tür parametrelerinin bazı alt kümelerinin belirli bir atamasının, kalan tür parametrelerini benzersiz bir şekilde belirlediğini iddia edebilir. Örneğin, türde bir durum parametresi taşıyan genel bir monad , tür sınıfı kısıtlamasını karşılar . Bu kısıtlamada işlevsel bir bağımlılık vardır . Bu, class türündeki belirli bir monad için , erişilebilen durum türünün benzersiz olarak belirlendiği anlamına gelir. Bu, derleyiciye tür çıkarımında yardımcı olur ve programcıya tür yönelimli programlamada yardımcı olur . msMonad.State s mm -> smMonad.Statem

Simon Peyton-Jones , karmaşıklık gerekçesiyle Haskell'de işlevsel bağımlılıkların getirilmesine itiraz etti.

Tip sınıfları ve örtük parametreler

Tip sınıfları ve örtük parametreler, tamamen aynı olmasa da, doğada çok benzerdir. Aşağıdaki gibi bir tür sınıfı kısıtlamasına sahip polimorfik bir işlev:

sum :: Num a => [a] -> a

bir örneğini dolaylı olarak kabul eden bir işlev olarak sezgisel olarak ele alınabilir Num:

sum_ :: Num_ a -> [a] -> a

Örnek Num_ a, esasen, örneğinin tanımını içeren bir kayıttır Num a. (Aslında bu, Glasgow Haskell Derleyicisi tarafından başlık altında tip sınıflarının nasıl uygulandığıdır.)

Ancak çok önemli bir fark vardır: örtük parametreler daha esnektir – farklı örneklerini iletebilirsiniz Num Int. Buna karşılık, tür sınıfları , herhangi bir tür için yalnızca bir benzersiz örnek seçiminin olmasını gerektiren sözde tutarlılık özelliğini zorlar . Tutarlılık özelliği, tür sınıflarını bir şekilde antimodüler yapar, bu nedenle yetim örneklerin (sınıfı veya ilgi türünü içermeyen bir modülde tanımlanan örnekler) kesinlikle önerilmez. Öte yandan, tutarlılık, programcıya aynı kodun iki ayrık parçasının aynı örneği paylaşacağını garanti ederek dile ek bir güvenlik düzeyi ekler.

Örnek olarak, sıralı bir küme ( tipinde Set a), çalışması için öğelerde ( tipinde ) toplam sıralama gerektirir a. Bu Ord a, öğeler üzerinde bir karşılaştırma operatörü tanımlayan bir kısıtlama ile kanıtlanabilir . Bununla birlikte, toplam bir düzen dayatmanın birçok yolu olabilir. Küme algoritmaları genellikle bir küme oluşturulduktan sonra sıralamadaki değişikliklere karşı toleranssız olduğundan Ord a, küme üzerinde çalışan fonksiyonlara uyumsuz bir örnek iletmek yanlış sonuçlara (veya çökmelere) neden olabilir. Bu nedenle, Ord abu özel senaryoda tutarlılığın sağlanması çok önemlidir.

Scala tipi sınıflardaki örnekler (veya "sözlükler"), tamamen ayrı bir tür varlıktan ziyade dilde sıradan değerlerdir. Bu örnekler varsayılan olarak, açıkça bildirilen örtük biçimsel parametreler için örtük gerçek parametreler olarak kullanılacak kapsamda uygun örnekler bularak sağlanırken, sıradan değerler olmaları, belirsizliği gidermek için açıkça sağlanabilecekleri anlamına gelir. Sonuç olarak, Scala tipi sınıflar tutarlılık özelliğini karşılamaz ve örtük parametreler için etkin bir sözdizimsel şekerdir.

Bu, Cats dokümantasyonundan alınan bir örnektir:

// A type class to provide textual representation
trait Show[A] {
  def show(f: A): String
}

// A polymorphic function that works only when there is an implicit 
// instance of Show[A] available
def log[A](a: A)(implicit s: Show[A]) = println(s.show(a))

// An instance for String
implicit val stringShow = new Show[String] {
  def show(s: String) = s
}

// The parameter stringShow was inserted by the compiler.
scala> log("a string")
a string

Coq (sürüm 8.2 ve sonrası), uygun örnekleri çıkararak tür sınıflarını da destekler. Agda 2'nin son sürümleri de "örnek argümanları" adı verilen benzer bir özellik sunar.

Operatör aşırı yüklemesine diğer yaklaşımlar

Olarak standart ML , "eşitlik türleri" mekanizması Haskell'ın yerleşik tip sınıfı kabaca karşılık Eq, ancak tüm Eşitlik operatörleri derleyici tarafından otomatik olarak elde edilir. Programcının süreç üzerindeki kontrolü, bir yapıdaki hangi tür bileşenlerin eşitlik türleri olduğunu ve bir polimorfik türdeki hangi tür değişkenlerin eşitlik türleri üzerinde olduğunu belirlemekle sınırlıdır.

SML'ler ve OCaml'in modülleri ve functorları, Haskell'in tip sınıflarına benzer bir rol oynayabilir, temel fark, tip sınıflarını geçici polimorfizm için uygun kılan tip çıkarımının rolüdür . OCaml'in nesne yönelimli alt kümesi , tür sınıflarından biriyle bir şekilde karşılaştırılabilir olan başka bir yaklaşımdır.

İlgili kavramlar

Aşırı yüklenmiş veriler ( GHC'de uygulanmış ) için benzer bir kavram family tipindedir .

Gelen C ++ C ++ gibi 20 kullanılarak tip sınıfları için destek kavramlar (C ++) . Örnek olarak, yukarıda bahsedilen Haskell typeclass Eq örneği şu şekilde yazılabilir:

template <typename T>
concept Equal =
      requires (T a, T b) {
            { a == b } -> std::convertible_to<bool>;
            { a != b } -> std::convertible_to<bool>;
};

Gelen Temiz typeclasses Haskell benzer, ancak biraz daha farklı bir sözdizimi vardır.

Rust , tutarlılığa sahip sınırlı bir tür sınıfı olan özellikleri destekler .

Merkür , Haskell'deki ile tam olarak aynı olmasa da, tip sınıflarına sahiptir.

In Scala , tip sınıfları bir olan programlama deyim dili mevcut örtülü parametreler değil, ayrı bir dil özelliği haddi zatında gibi özellikleri ile uygulanabilir. Scala'da uygulanma biçimleri nedeniyle, belirsizlik durumunda kodda belirli bir yerde bir tür için hangi tür sınıf örneğinin kullanılacağını açıkça belirtmek mümkündür. Ancak, belirsiz türdeki sınıf örnekleri hataya açık olabileceğinden, bu mutlaka bir avantaj değildir.

Prova yardımcısı Coq , son sürümlerde tip sınıflarını da destekledi. Sıradan programlama dillerinden farklı olarak, Coq'ta, tür sınıfı tanımında belirtilen bir tür sınıfının herhangi bir yasası (monad yasaları gibi), kullanılmadan önce her bir tür sınıfı örneği için matematiksel olarak kanıtlanmalıdır.

Ayrıca bakınız

Referanslar

Dış bağlantılar