Scala'da daha yüksek türde olan nedir?


275

Web'de aşağıdakileri bulabilirsiniz:

  1. Daha yüksek tür türü == tür oluşturucu?

    class AClass[T]{...} // For example, class List[T]

    Bazıları bunun daha yüksek bir tür olduğunu söylüyor, çünkü tanımla uyumlu olacak türler üzerine soyutlanıyor.

    Daha yüksek tür türleri , diğer türleri alan ve yeni bir tür oluşturan türlerdir

    Bunlar tip yapıcı olarak da bilinir . (Örneğin, Scala'da Programlama'da ).

  2. Type parametresini type parametresi olarak alan daha yüksek kinded type == type yapıcısı?

    Daha Yüksek Bir Tür Generics makalesinde okuyabilirsiniz

    ... türlere göre soyutlanan türler (türlere göre daha yüksek türler) ... "

    ki bu

    class XClass[M[T]]{...} // or
    
    trait YTrait[N[_]]{...} // e.g. trait Functor[F[_]]
    

    daha yüksek bir türdür.

Yani bu akılda ile, ayırt etmek zordur tür kurucusu , yüksek kinded tip ve tip parametre olarak tip kurucular alır tür kurucusu nedenle soru yukarıda.


Landei'nin Functor'u örnek olarak eklendi.
Lutz

Yanıtlar:


284

Biraz karışıklığa yol açarak bu karışıklığın bir kısmını başlatmak için telafi edeyim. İnsanları daha aşina olma eğiliminde olduğundan, benzetmeyi bunu açıklamak için değer seviyesinden kullanmayı seviyorum.

Tür yapıcısı, bir türü "oluşturmak" için tür bağımsız değişkenlerine uygulayabileceğiniz türdür.

Değer yapıcısı, bir değeri "oluşturmak" için değer bağımsız değişkenlerine uygulayabileceğiniz bir değerdir.

Değer yapıcılara genellikle "işlevler" veya "yöntemler" denir. Bu "yapıcıların" aynı zamanda "polimorfik" olduğu söylenir (çünkü bunlar "şekil" şeklinde "şeyler" oluşturmak için kullanılabilirler) veya "soyutlamalar" (çünkü farklı polimorfik örneklemeler arasında neyin değiştiğinin üzerinde soyutlandıkları için) kullanılabilir.

Soyutlama / polimorfizm bağlamında, birinci dereceden soyutlamanın "tek kullanımı" anlamına gelir: bir kez bir tür üzerinde soyutlanırsınız, ancak bu türün kendisi hiçbir şey üzerinde soyut olamaz. Java 5 jenerikleri birinci derecedir.

Yukarıdaki soyutlamaların birinci dereceden yorumu şu şekildedir:

Tür yapıcısı, uygun bir türü "oluşturmak" için uygun tür argümanlarına uygulayabileceğiniz bir türdür.

Değer yapıcı, uygun bir değeri "oluşturmak" için uygun değer bağımsız değişkenlerine uygulayabileceğiniz bir değerdir.

Dahil herhangi bir soyutlama vurgulamak için (sanırım bu "sıfır-sıra" diyebiliriz, ama bu herhangi bir yerde kullanılan görmedim), değer 1veya türü gibi String, biz genellikle bir şey "uygun" bir değer veya tip olduğunu söylüyorlar.

Uygun bir değer, argümanları beklememesi anlamında "hemen kullanılabilir" (bunlar üzerinde soyutlama yapmaz). Bunları kolayca yazdırabileceğiniz / inceleyebileceğiniz değerler olarak düşünün (bir işlevi seri hale getirmek hile yapıyor!).

Uygun bir tür, değerleri sınıflandıran bir türdür (değer yapıcılar dahil), tür yapıcılar herhangi bir değeri sınıflandırmaz (uygun bir tür elde etmek için önce doğru tür bağımsız değişkenlerine uygulanması gerekir). Bir türü başlatmak için, uygun bir tür olması gerekir (ancak yeterli değildir). (Soyut bir sınıf veya erişiminiz olmayan bir sınıf olabilir.)

"Yüksek mertebe" basitçe polimorfizm / soyutlamanın tekrarlanan kullanımı anlamına gelen jenerik bir terimdir. Polimorfik tipler ve değerler için aynı anlama gelir. Somut olarak, daha üst düzey bir soyutlama, bir şeyin üzerine soyutlanan bir şeyden soyutlanır. Tipler için, "daha üst düzey" terimi daha genel "daha üst düzey" in özel amaçlı bir sürümüdür.

Böylece, karakterizasyonumuzun üst düzey versiyonu şöyle olur:

Tür yapıcısı, uygun bir türü (kurucu) "oluşturmak" için tür argümanlarına (uygun türler veya tür yapıcıları) uygulayabileceğiniz bir türdür.

Değer yapıcısı, uygun bir değeri (yapıcı) "oluşturmak" için değer bağımsız değişkenlerine (uygun değerler veya değer yapıcıları) uygulayabileceğiniz bir değerdir.

Böylece, "üst düzey" basitçe "X üzerinden soyutlama" derken, gerçekten demek istediğiniz anlamına gelir! Bu Xsoyutlanan, kendi "soyutlama haklarını" kaybetmez: istediği her şeyi soyutlayabilir. (Bu arada, burada "soyut" fiilini kullanıyorum: bir değerin veya türün tanımı için gerekli olmayan bir şeyi dışarıda bırakmak, böylece soyutlamanın kullanıcısı tarafından bir argüman olarak değiştirilebilir / sağlanabilir .)

Aşağıda, uygun, birinci dereceden ve daha yüksek seviyeli değerler ve türlerden bazı örnekler (Lutz'un sorularını e-posta ile esinlenerek) görebilirsiniz:

                   proper    first-order           higher-order

values             10        (x: Int) => x         (f: (Int => Int)) => f(10)
types (classes)    String    List                  Functor
types              String    ({type λ[x] = x})#λ   ({type λ[F[x]] = F[String]})#λ

Kullanılan sınıflar şu şekilde tanımlanmıştır:

class String
class List[T]
class Functor[F[_]]

Sınıfları tanımlayarak dolaylı yoldan kaçınmak için, bir şekilde doğrudan Scala'da ifade edilemeyen anonim tip işlevlerini ifade etmeniz gerekir, ancak çok fazla sözdizimsel yükü olmayan yapısal türleri kullanabilirsiniz ( -style, https://stackoverflow.com adresinden kaynaklanmaktadır. / users / 160378 / retronym afaik) ile ilişkili olan kısmını dışarı aktarmak suretiyle yedek oluşturmanız gerekir :

Scala'nın anonim tür işlevlerini destekleyen bazı varsayımsal gelecekteki sürümlerinde, bu son satırı örneklerden kısaltabilirsiniz:

types (informally) String    [x] => x              [F[x]] => F[String]) // I repeat, this is not valid Scala, and might never be

(Kişisel bir notta, "daha yüksek türler" hakkında konuştuğum için pişman oldum, sonuçta sadece türler! Kesinlikle netleştirmeniz gerektiğinde, "type constructor parametresi", "type constructor member" gibi şeyleri söylemenizi öneririm. veya "tür oluşturucu takma adı" nı seçerek yalnızca uygun türlerden bahsetmediğinizi vurgulayın.)

ps: Konuları daha da karmaşıklaştırmak için, "polimorfik" farklı bir şekilde belirsizdir, çünkü polimorfik tip bazen Forall T, T => Tpolimorfik değerleri sınıflandırdığından (Scala'da bu değer, yapısal tip olarak yazılmıştır {def apply[T](x: T): T = x})




Daha yüksek akraba olarak okumaya devam ediyorum ve akraba ruhu hayal
ediyorum

110

(Bu cevap Adriaan Moors yanıtını bazı grafik ve tarihi bilgilerle dekore etme girişimidir.)

Daha yüksek türler 2.5'ten beri Scala'nın bir parçasıdır.

  • Bundan önce Scala, şimdiye kadar Java olarak, bir tür yapıcısına tür parametresi olarak kullanılmak üzere tür yapıcısının (Java'da "jenerikler") kullanılmasına izin vermedi. Örneğin

     trait Monad [M[_]]

    mümkün değildi.

    Scala 2.5'te tip sistemi, tipleri daha yüksek bir seviyede ( tip yapıcı polimorfizm olarak bilinir) sınıflandırma kabiliyeti ile genişletilmiştir . Bu sınıflandırma tür olarak bilinir.

    Tür ve tür realtion, ** daha yüksek türde jenerikler ( Daha Yüksek Türlü Jeneriklerden türetilen resim )

    Sonuç olarak, bu tip yapıcı (örn. List), Tip yapıcılarının tip parametresi konumundaki diğer tipler gibi kullanılabilir ve böylece Scala 2.5'ten bu yana birinci sınıf tip haline geldiler. (Scala'da birinci sınıf değerler olan fonksiyonlara benzer).

    Daha yüksek türlü destek tip sistemi bağlamda, ayırt edebilir uygun tipleri , çeşitleri gibi Intya da List[Int]birinci derece gibi türleri Listve daha yüksek bir tür türleri gibi Functorya da Monad(tip türleri üzerinde arka olan türleri üzerinde arka olan).

    Diğer taraftan Java'nın tip sistemi çeşitleri desteklemez ve bu nedenle "daha yüksek tür" türlerine sahip değildir.

    Bu yüzden, destekleyici tip sistemin arka planında görülmelidir.

  • Scala söz konusu olduğunda, genellikle

     trait Iterable[A, Container[_]]

    "Daha yüksek tür tipleri" başlığı ile, örneğin genel programcılar için Scala'da, bölüm 4.3

    Bu bazen birçok atıfta çünkü missleading olduğu Containerkadar yüksek kinded türü değil Iterable, daha kesin, ama ne

    Containerburada daha yüksek tür (yüksek dereceli) tipte bir tür yapıcı parametresi kullanımı Iterable.


80

Tür sıradan gibi türleri Intve Charörnekleri değerleri, vardır *. Gibi tekli tip kurucular tür MaybeIS * -> *; gibi Either( curried ) tür ikili yapıcıları * -> * -> *, vb. Tür düzeyindeki işlevler gibi Maybeve Eitherbunlar gibi türleri görüntüleyebilirsiniz : bir veya daha fazla tür alırlar ve bir tür döndürürler.

Bir fonksiyonu daha yüksek dereceden bir varsa mertebeden sipariş işlevi oklar, sola, (gayri) iç içe geçme derinliği 1 den büyük,:

  • Sipariş 0: 1 :: Int
  • Sipariş 1: chr :: Int -> Char
  • Sipariş 2: fix :: (a -> a) -> a,map :: (a -> b) -> [a] -> [b]
  • Sipariş 3: ((A -> B) -> C) -> D
  • Sipariş 4: (((A -> B) -> C) -> D) -> E

Yani, uzun öykü kısa, daha yüksek tür bir tür sadece tür düzeyinde bir üst düzey işlevdir.

  • Sipariş 0: Int :: *
  • Sipariş 1: Maybe :: * -> *
  • Sıra 2: Functor :: (* -> *) -> Constraint—daha yüksek-tür: tekli tip kurucuları tip-sınıf kısıtlamalarına dönüştürür

Tamam anladım, o zaman (* ⇒ *) ⇒ * ve (* ⇒ *) ⇒ (* ⇒ *) için Scala'da bir örnek ne olurdu? Landei Functor'ı birinci kategoriye mi yoksa ikinci kategoriye mi sığar?
Lutz

1
@lutz: İlk kategoride olurdu: bir tür yapıcısından Functoruygun bir tür (iyi, özellik, ama aynı fikir) üretir . Functor[F[_]]F
Jon Purdy

1
@Jon: Çok anlayışlı bir yazı, teşekkür ederim. Tip dönüştürücü (* => *) => (* => *)Scala'da ifade edilebilir mi? Değilse, başka bir dilde mi?
Eugen Labun

@JonPurdy Körelme * ⇒ * ⇒ *ile karşılaştırma çok faydalıdır. Teşekkürler!
Lifu Huang

(* ⇒ *) ⇒ (* ⇒ *)ayrıca hecelenebilir (* ⇒ *) ⇒ * ⇒ *. Scala gibi ifade edilebilir Foo[F[_], T]. Bu tür (Haskell'de) newtype Twice f a = Twice (f (f a))(örneğin, Twice Maybe IntMaybe (Maybe Int), Twice [] Char[[Char]]) veya serbest monad gibi daha ilginç bir tür data Free f a = Pure a | Free (f (Free f a)).
Jon Purdy

37

Şunu söyleyebilirim: Daha yüksek bir tür , bir tür yapıcıya göre özetler . Örneğin düşünün

trait Functor [F[_]] {
   def map[A,B] (fn: A=>B)(fa: F[A]): F[B]
}

İşte Functor"daha yüksek türlü bir tür" ("Yüksek türün jenerikleri " kağıdında kullanıldığı gibi ). Somut ("birinci dereceden") tipte bir yapıcı değildir List(sadece uygun tiplerin üzerine çıkar). Tüm tekli ("birinci dereceden") tip yapıcıları (ile gösterildiği gibi) özetler F[_].

Ya da başka bir deyişle: Java'da açık bir şekilde yapıcılarımız var (örneğin List<T>), ancak "daha yüksek türlü" türlerimiz yok, çünkü bunların üzerinde soyutlayamayız (örn. FunctorYukarıda tanımlanan arayüzü yazamayız - en azından doğrudan değil ).

"Yüksek mertebeden (tip yapıcı) polimorfizm" terimi, "yüksek cins türleri" destekleyen sistemleri tarif etmek için kullanılır.


Ben de öyle düşünmüştüm, fakat Jon'un cevabı ile çelişiyor gibi görünüyor.
Lutz

3
Evet. Jon'un List<T>Java'ya verdiği cevaba göre (anladığım kadarıyla) açıkça bir tür olduğu için tek tip bir yapıcı olurdu * -> *. Jon'un cevabında eksik olan şey *, daha yüksek bir tür olarak adlandırmak için "bütün şey" (sadece Java'da olduğu gibi değil) üzerinde özetleyebilmenizdir.
Landei

@Landai: Kağıt genel programcılar Scala bölüm 4.3'de sürekli iterable [A, Container [_]] (Yineleyici Konteyner kastedilmektedir eğer açık olmasa da) daha yüksek kinded türü önermektedir burada diğer tarafta vero690 içinde bölüm 2.3.1 , Yineleyiciye veya Functor özelliğinize benzeyen (* -> *) -> * (yüksek dereceli tip oluşturucu ile parametrelenen tip operatörü) gibi bir şey için daha yüksek tür tip yapıcı terimini kullanır .
Lutz

1
Bu muhtemelen doğru, ama sanırım burada saçları ayırmaya başlıyoruz. Daha yüksek tür tipleri ile ilgili önemli nokta, sadece tip yapıcıların dahil edilmemesi (bir tip yapıcı polimorfizm siparişi) değil, aynı zamanda bu tip yapıcıların (yüksek dereceli tip yapıcı polimorfizm) somut tipini de özetleyebilmemizdir. Kısıtlama olmaksızın (türler ve tür oluşturucular ile ilgili) istediğimiz her şeyi soyutlama yeteneğine sahibiz, bu da bu özelliğin tüm olası sürümlerini adlandırmayı daha az ilginç hale getirir. Ve beynimi acıtıyor.
Landei

2
Genel olarak, burada tanımları ve referansları ayırt etmek önemlidir. Tanım def succ(x: Int) = x+1"değer yapıcısı" nı tanıtır (bununla ne demek istediğime dair diğer succcevabıma bakın ) (hiç kimse bu değere succ (x: Int) demez). Benzer şekilde, Functorcevabınızda tanımlanmış (gerçekten daha yüksek tür) bir tiptir. Yine, gibi anlamlara olmamalıdır Functor[F[_]](ne Fnedir? _Onlar kapsamında değiliz maalesef sular burada yaparak existentials muddies için sözdizimsel şeker?! F[_]Kısaca F[T forSome {type T}])
Adriaan Moors

1

Scala REPL sağlayan :kindkomutu hangi

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.

Örneğin,

scala> trait Foo[A]
trait Foo

scala> trait Bar[F[_]]
trait Bar

scala> :kind -v Foo
Foo's kind is F[A]
* -> *
This is a type constructor: a 1st-order-kinded type.

scala> :kind -v Foo[Int]
Foo[Int]'s kind is A
*
This is a proper type.

scala> :kind -v Bar
Bar's kind is X[F[A]]
(* -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.

scala> :kind -v Bar[Foo]
Bar[Foo]'s kind is A
*
This is a proper type.

:helpBen bütünüyle buraya değer gönderme onu düşünüyorum çok net tanımları sağlar (Scala 2.13.2)

scala> :help kind

:kind [-v] <type>
Displays the kind of a given type.

    -v      Displays verbose info.

"Kind" is a word used to classify types and type constructors
according to their level of abstractness.

Concrete, fully specified types such as `Int` and `Option[Int]`
are called "proper types" and denoted as `A` using Scala
notation, or with the `*` symbol.

    scala> :kind Option[Int]
    Option[Int]'s kind is A

In the above, `Option` is an example of a first-order type
constructor, which is denoted as `F[A]` using Scala notation, or
* -> * using the star notation. `:kind` also includes variance
information in its output, so if we ask for the kind of `Option`,
we actually see `F[+A]`:

    scala> :k -v Option
    Option's kind is F[+A]
    * -(+)-> *
    This is a type constructor: a 1st-order-kinded type.

When you have more complicated types, `:kind` can be used to find
out what you need to pass in.

    scala> trait ~>[-F1[_], +F2[_]] {}
    scala> :kind ~>
    ~>'s kind is X[-F1[A1],+F2[A2]]

This shows that `~>` accepts something of `F[A]` kind, such as
`List` or `Vector`. It's an example of a type constructor that
abstracts over type constructors, also known as a higher-order
type constructor or a higher-kinded type.
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.