Bir tür ve bir tür arasındaki fark nedir?


26

Programlama dilbilgisi Haskell'i öğreniyorum ve kafamı a typeile a arasındaki farkın etrafına sarmaya çalışıyorum kind.

Anladığım kadarıyla a kind is a type of type. Mesela a ford is a type of carve a car is a kind of vehicle.

Bu, bunu düşünmek için iyi bir yol mu?

Yolu beynim şu anda kablolu Çünkü bir ford is a **type** of cardeğil, aynı zamanda bir car is a **type** of vehicleaynı zaman a iken car is a **kind** of vehicle. Terimleri yani typeve kindbirbirleriyle değiştirilebilir.

Birisi buna ışık tutabilir mi?


6
Bu tartışmaya yol açan Yığın Taşması yazısından yeni geldim. Ayrıntılı olarak cevaplamaya yetkin olduğumdan emin değilim - ama "tür" ve "tür" terimleri hakkında gerçekten çok fazla kelimelisiniz, onları İngilizce'deki anlamlarıyla ilişkilendirmeye çalışırken (gerçekten eşanlamlılar) ). Onlara teknik terimler gibi davranmalısın. "Tür", tüm programcılar tarafından iyi anlaşıldığını varsayalım, çünkü her dil için kavramın hayati önem taşıdığı, Javascript gibi zayıf yazılanların bile, "Tür", Haskell'de "tür türü" için kullanılan teknik bir terim olduğunu. Orada gerçekten hepsi bu.
Robin Zigmond

2
@RobinZigmond: Bunların teknik terimler olduğu konusunda haklısınız, ancak bunlar Haskell'den daha yaygın olarak kullanılıyor. Belki de bu soruyu ele alan Yığın Taşması tartışmalarına geri dönelim?
Andrej Bauer

@AndrejBauer Onların Haskell dışında kullanılmadıklarını asla söylemedim, kesinlikle "type" dediğim gibi her dilde kullanılıyor. Asla Haskell'in dışında asla "nazik" olmadım, ama sonra Haskell hiç tanımadığım tek fonksiyonel dil ve terimin başka yerde kullanılmadığını, sadece bu şekilde kullanıldığını söylememe dikkat ettim. Haskell. (İstediğiniz gibi bağlantı burada )
Robin Zigmond

ML ailesi dillerinin de çeşitleri vardır, örneğin Standart ML ve OCaml. Bence, bu isim açıkça belli değil. İmza olarak tezahür ederler ve elementlerine yapı denir .
Andrej Bauer

1
Daha doğru bir İngiliz benzetmesi Ford bir otomobil türüdür ve otomobil bir araç türüdür ancak hem otomobil hem de araç tipleri aynı tiptedir: isimler. Oysa kırmızı, bir araba rengi, RPM ise bir araba performansı ölçümü türüdür ve her ikisi de aynı türdendir: sıfatlar.
slebetman

Yanıtlar:


32

Burada, "değerler", "türler" ve "türler" resmi anlamlara sahiptir, bu nedenle ortak İngilizce kullanımlarını veya otomobilleri sınıflandırma analojilerini göz önünde bulundurmanız yalnızca size çok yardımcı olacaktır.

Cevabım, özellikle Haskell bağlamında bu terimlerin biçimsel anlamları ile ilgilidir; bu anlamlar matematikle / CS "tip teorisi" nde kullanılan anlamlara dayandırılmıştır (aslında aynı değildir). Yani, bu çok iyi bir "bilgisayar bilimi" cevabı olmayacak, ama oldukça iyi bir Haskell cevabı olarak hizmet etmeli.

Haskell'de (ve diğer dillerde), ifadenin sahip olmasına izin verilen değer sınıfını tanımlayan bir program ifadesine bir tür atamak yararlı olur . Ben bunu ifadede olduğunu bilmek faydalı olacaktır anlamak için yeterli örnek gördüm burada varsayıyoruz , değişkenler ve her zaman türünün değerlerini olacak değil, demek, ve sırasıyla. Temelde, sahip türlerini geniş bir yelpazede üzerinde düzgün çalışacağını ifadeleri / programların yazılı olarak bize yardımcı değerler .sqrt (a**2 + b**2)abDoubleStringBool

Şimdi, farkına varmamış olabileceğiniz bir şey, Haskell tiplerinin, tip imzalarında görünenlere benzemesidir:

fmap :: Functor f => (a -> b) -> f a -> f b

aslında kendileri de bir seviye-seviye Haskell alt dilinde yazılmıştır. Program metni Functor f => (a -> b) -> f a -> f b- tam anlamıyla - bu alt dilde yazılmış bir tür ifadedir . Altdili (örneğin operatör içerir ->bu dilde bir sağ taraf infix operatörüdür), değişkenler (örneğin f, ave b) diğerine tipi ifade ve "uygulama" (örneğin, f abir fuygulanan a).

İfade değerleri sınıflarını tanımlamak için program ifadelerine tipler atamanın birçok dilde nasıl bir faydası olduğunu söylemiş miydim? Eh, bu tip seviyeli alt dilde, ifadeler türlere ( değerlerden ziyade ) değerlendirilir ve temsil edilmelerine izin verilen türlerin sınıflarını tanımlamak için tür ifadelerine tür atamak yardımcı olur . Temel olarak, türlere sahip olmak, çok çeşitli türlerde doğru şekilde çalışacak türdeki yazım ifadelerinde bize yardımcı olur .

Yani, değerler şunlardır türleri olarak türleri şunlardır türlü ve türleri bize yazmanıza yardımcı değeri ise -seviye programlar türlü bize yazmanıza yardımcı tip -seviye programları.

Bu tür neye benziyor? Peki, imza türünü düşünün:

id :: a -> a

Tip ifadesi ise a -> ageçerli olmak ne tür bir türlerine biz değişken izin vermeli aolunur? Eh, tür ifadeleri:

Int -> Int
Bool -> Bool

geçerli görünüyor, bu yüzden türleri Int ve Boolaçıkça doğru tür . Ancak daha karmaşık türler:

[Double] -> [Double]
Maybe [(Double,Int)] -> Maybe [(Double,Int)]

geçerli görünüyorsun Aslında, idfonksiyonlara çağrı yapabilmemiz gerektiğinden bile:

(a -> a) -> (a -> a)

iyi görünüyor. Yani, Int, Bool, [Double], Maybe [(Double,Int)], ve a -> abenzeri tüm göz tipleri hakkı tür .

Başka bir deyişle, sadece bir tane var gibi görünüyor tür , diyelim *Unix joker gibi, her tip aynı vardır tür * , hikayenin sonu.

Sağ?

Pek iyi değil. O çıkıyor Maybeolarak tek başına bütün, sadece geçerli bir tür ifadesi olarak ise, Maybe Int(hemen aynı şekilde sqrt, tek başına bütün, tıpkı geçerli bir değer ifadesi gibidir sqrt 25). Ancak , aşağıdaki tür ifadesi geçerli değil:

Maybe -> Maybe

Ederken, Çünkü Maybebir tür ifadesidir, bu temsil etmiyor tür bir tip değerlere sahip olabilir. Yani, işte biz tanımlamalıdır nasıl *- bu tür bir türlerine değerlerine sahip; neye "tam" türlerini içerir Doubleveya Maybe [(Double,Int)]dışlayan eksik, değersiz türleri gibi ama Either String. Basitlik için, *bu terminoloji evrensel olmasa da, "somut türler" C ++ programcısından çok farklı bir şey anlamına gelebilir.

Şimdi, tip ifadesinde a -> asürece tip olarak abulunur tür * (beton türlerinin tür), tip ifadenin sonucu a -> aolacaktır da sahip tür * (yani beton türlerinin tür).

Peki, tür ve tip olduğunu Maybe? Peki, Maybebaşka bir beton tipi elde etmek için beton tipine uygulanabilir. Yani, Maybebir alan bir tür düzeyinde fonksiyonu gibi biraz gibi görünüyor türü arasında tür * ve döner tip bir tür * . Biz sürdü bir değer seviyesi işlevini olsaydı değeri arasında tip Int ve döndürülen değer bir tip Int , biz bunu verecekti tip imzasını Int -> Intböylece kıyas yoluyla biz vermelidir, Maybebir tür imza * -> *. GHCi kabul eder:

> :kind Maybe
Maybe :: * -> *

Geri dönüyor:

fmap :: Functor f => (a -> b) -> f a -> f b

Bu tip imza olarak, değişken ftür vardır * -> *ve değişkenler ave bnazik olması *; yerleşik operatörün bir ->tür vardır * -> * -> *( *soldan bir tür sağdan ve sağdan bir tür alır ve aynı türden bir tür döndürür *). Bu ve nazik çıkarsama kurallarına itibaren, olmadığını anlıyoruz a -> btür geçerli bir türüdür *, f ave f btür geçerli türleri de vardır *ve (a -> b) -> f a -> f btürünün geçerli türüdür *.

Başka bir deyişle, derleyici (a -> b) -> f a -> f b, doğru türdeki değişkenler için geçerli olduğunu doğrulamak için tür ifadesini "tür kontrolü" yapabilir , doğru türdeki değişkenler için geçerli olduğunu doğrulamak için "tür kontrolleri" yazar sqrt (a**2 + b**2).

"Türler" e karşı "türler" için ayrı terimler kullanmanın nedeni (yani "türler" hakkında konuşmamak) çoğunlukla karışıklığı önlemek içindir. Çeşit çok farklı bir görünüm yukarıda tipleri , en azından başlangıçta, ve oldukça farklı davranır gibi görünüyor. (Örneğin, her "normal" tipi aynı tür olduğu fikri etrafında baş sarmak için biraz zaman alır *ve tür a -> bolduğu *değil * -> *.)

Bunlardan bazıları da tarihseldir. GHC Haskell geliştikçe, değerler, türler ve türler arasındaki farklılıklar bulanıklaşmaya başladı. Bu günlerde değerler türlere "yükseltilebilir" ve türler ve türler gerçekten aynı şeydir. Dolayısıyla, modern Haskell'de değerler hem türlere hem de ARE türlerine (neredeyse) sahiptir ve türlerin türleri sadece daha fazla türlerdir.

@ user21820, "türler ve türler gerçekten aynı şeydir" hakkında ek açıklamalar istedi. Biraz daha açık olmak gerekirse, modern GHC Haskell'de (8.0.1 sürümünden beri, sanırım), türler ve türler derleyici kodunun çoğunda eşit olarak ele alınmaktadır . Derleyici, sırasıyla bir değerin türü veya bir türün türü hakkında şikayet edip etmediğine bağlı olarak, "türler" ile "türler" arasında ayrım yapmak için bazı hatalar yapar.

Ayrıca, hiçbir uzantı etkinleştirilmemişse, yüzey dilinde kolayca ayırt edilebilirler. Örneğin, türlerin (değerlerin) sözdiziminde bir temsili vardır (örneğin, tür imzalarında), ancak türlerin (türlerinde) - bence - tamamen örtüktür ve göründükleri yerde açık bir sözdizimi yoktur.

Ancak uygun uzantıları açarsanız, türler ve türler arasındaki fark büyük ölçüde ortadan kalkar. Örneğin:

{-# LANGUAGE GADTs, TypeInType #-}
data Foo where
  Bar :: Bool -> * -> Foo

İşte, Bar(hem bir değer hem de) bir türdür. Bir tür olarak Bool -> * -> Foo, bir tür tür alan Bool(tür, aynı zamanda tür olan) ve tür tür alan *ve tür tür üreten tür düzeyinde bir işlevdir Foo. Yani:

type MyBar = Bar True Int

doğru kontroller.

@AndrejBauer'ın cevabında açıkladığı gibi, türler ve türler arasında ayrım yapmanın başarısızlığı güvensizdir - *türünün / türünün kendisi (modern Haskell'deki gibi) paradokslara yol açan bir tür / tür olması. Bununla birlikte, Haskell'in tür sistemi sonlandırılmadığı için zaten paradokslarla doludur, bu yüzden büyük bir sorun olarak kabul edilmez.


"Tipleri ve çeşitleri gerçekten aynı şeyler", o zaman tipi typeadildir typekendisi ve herkes için de hiç gerek olmazdı kind. Peki ayrım tam olarak nedir?
user21820,

1
@ user21820, buna hitap edebilecek sona bir not ekledim Kısa cevap: Modern GHC Haskell'de gerçekten bir ayrım yoktur .
KA Buhr,

1
Bu harika bir cevap - paylaşım için çok teşekkürler. İyi yazılmış ve yavaş yavaş kavramları tanıtıyor - Haskell'i birkaç yıldır yazmamış biri olarak, bu çok takdir edilmektedir!
ultrafez 19

@KABuhr: Bu eklenen bit için teşekkürler!
user21820

19

type:kind=set:class.

  • Bool bir tür
  • Type bir tür çünkü unsurları tür
  • Bool -> Int bir tür
  • Bool -> Type bir tür çünkü unsurları tür döndüren işlevlerdir
  • Bool * Int bir tür
  • Bool * Type bir tür çünkü unsurları bir bileşen bir tür çiftler

U0U1U2U0BoolNatNatNatU1U0BoolU0U0U0Un+1UnUn×

U0U1U0U1U0**U_1


2
(GHC) Haskell'in evren kavramının olduğunu sanmıyorum. Type :: Typebir aksiyomdur. "Tür" ve "tür" arasındaki ayrım, tamamen bu durumda insan dilindedir. Truebir türü vardır Boolve Boolkendi türünde bir türü Typevardır Type. Bazen bir tür denir, bunun tür düzeyinde bir varlığın türü olduğunu vurgulamak için adlandırırız, ancak Haskell'de yine de sadece bir türdür. Evrenler gerçekte Coq gibi var olduğu bir sistemde, daha sonra "tip" bir evren ve başka "türden" anlamlara gelebilir, ama o zaman biz genellikle sonsuz sayıda evrenler istiyorum.
HTNW

1
Buradaki ayrım sadece "insan dili" değildir, temel tip sistemde resmi bir ayrımdır. Type :: TypeTürler ve türler arasında hem de hem de bir ayrım olması oldukça mümkündür . Ayrıca, Type :: TypeHaskell'de hangi kod parçasını gösterir ?
Andrej Bauer

1
Ayrıca *Haskell'de bir tür evren olduğunu söylemeliyim . Sadece buna öyle demiyorlar.
Andrej Bauer

3
@AndrejBauer Typegelen Data.Kindsve *olmalıdır eş. Başlangıçta sadece *ilkel olarak sahip olduk , bugünlerde GHC.Types.Typeiç modülde olduğu gibi dahili olarak tanımlanmış GHC.Types, sırayla olarak tanımlanmış type Type = TYPE LiftedRep. Bence TYPEtür ilkesi, tür ailesi (kaldırılmış tipler, kutusuz tipler ...). Buradaki "inelegant" karmaşıklığının çoğu, gerçek tip teorik nedenlerle değil, bazı düşük seviyeli optimizasyonları desteklemektir.
chi,

1
Özetlemeye çalışacağım. Eğer vbir değerdir, o zaman bir türü vardır: v :: T. Eğer Ttürüdür, o zaman bir türü vardır: T :: K. Türün türüne denir. TYPE repNadir görünen kelimelere benzeyen tiplere çeşit denilebilir. IFF T :: TYPE repolan Tbir önceki çözümün üzerinde görünmesine izin ::. "Nazik" kelimesi buna nüanslıdır: Kiçinde T :: Kbir tür ama içinde değildir v :: K, ancak aynıdır K. " KTürünün bir sıralama ise" bir tür "aka" türlerinin RHS'sinde olduğunu ::" tanımlayabiliriz , ancak bu kullanımı doğru şekilde yakalamaz. Bu yüzden benim "insan ayrımcılığım" pozisyonum.
HTNW,

5

Bir değer , araba yolunuzda oturduğunuz 19.206 mil ile kırmızı 2011 Ford Mustang'a özgüdür.

Bu spesifik değerin gayrı resmi olarak birçok çeşidi olabilir : bir Mustang, ve bir Ford ve bir otomobil, ve bir araç, yapabileceğiniz birçok diğer tür arasında (türlerin "türü") Size ait "veya" kırmızı olan şeyler "türü veya ...).

(Haskell'de, birinci dereceden bir yaklaşıma göre (GADT'ler bu özelliği kırarlar ve sayı değişmezleri ve OverloadedStrings uzantısının etrafındaki sihir onu biraz gizler), değerler size vereceğiniz enformel "tip" plethora yerine bir ana tipe sahiptir. . stang 42Bu açıklama, bir amaçları için, olduğu Int; orada Haskell hiçbir türü "numaralar" veya "hatta tamsayılar" içindir -ya da daha doğrusu, bir tane yapabiliriz, ama bir ayrık tip olacaktır Int).

Şimdi, "Mustang" , "araba" nın bir alt türü olabilir - bir Mustang olan her değer aynı zamanda bir arabadır. Ama tip -veya, Haskell'ın terminolojisini kullanmak, nazik "Mustang" nin "otomobil" değildir. "Mustang" türü, araba sürdüğünüzde park edebileceğiniz veya etrafa sürebileceğiniz bir şey değildir. "Mustang" bir isim, bir kategori veya sadece bir türdür. Bunlar, gayri vardır çeşit "Mustang" nin.

. (Yine Haskell yalnızca Yani her tip düzey şey için bir tür tanır Inttür vardır *ve başka hiçbir çeşit. MaybeNazik vardır * -> *ve başka hiçbir çeşit Ama sezgi hala düzenlemeliyiz. 42Bir olan Int, ve yapabileceğiniz Intonunla y şeyler Toplama ve çıkarma gibi. IntKendisi bir değildir Int, böyle bir sayı yoktur Int + Int. Gayrı resmi olarak insanların bir tür olduğunu söyleyebilirsin, Intbunun için türü için bir sınıf sınıfı örneğiNum olduğu anlamına gelir - bu aynı şey değildir. şeklindeki sözleri vardır tür . Haskell yazıldığından tür "türü" vardır .)NumIntInt NumInt*

Öyleyse her gayri resmi "tür" sadece bir isim veya kategori değil mi? Tüm tipler aynı türde midir? Çok sıkıcıyken neden çeşitlerden bahsediyorsun?

Bu, İngiliz analojisinin biraz sertleşeceği, ancak benimle birlikte kaldığı yer: İngilizce'deki "sahip" kelimesinin, sahip olunan şeyin bir tanımı olmadan, hiçbir anlam ifade etmiyormuş gibi davran. Birisi size "sahip" diyorsa, bunun size hiç bir anlamı olmayacakmış gibi yapın; ama eğer biri size "araba sahibi" diyorsa, ne demek istediklerini anlayabilirsiniz.

"Sahip", "araba" ile aynı türde değildir , çünkü bir araba hakkında konuşabilirsiniz, ancak İngilizce'nin bu makyaj sürümünde sahibi hakkında konuşamazsınız. Sadece bir "araç sahibi" hakkında konuşabilirsiniz. "Sahip", "araba" gibi, "isim" gibi bir şeye uygulandığı zaman, sadece "isim" gibi bir şey yaratır. "Sahip" türünün "isim -> isim" olduğunu söyleyebiliriz. "Sahip", bir isim alan ve bundan farklı bir isim üreten bir işlev gibidir; ama bu bir isim değil.

"Araba sahibinin", "araba" nın bir alt türü olmadığını unutmayın! Araba kabul eden veya iade eden bir işlev değil! Bu sadece "araba" dan tamamen ayrı bir tip. Bir noktada belirli miktarda paraya sahip iki kolu ve iki bacağı olan değerleri açıklar ve bu parayı bir satıcıya götürür. Dört tekerleği ve bir boya işi olan değerleri tanımlamaz. Ayrıca "araç sahibi" ve "köpek sahibi" nin farklı türler olduğunu ve bunlardan biriyle yapmak isteyebileceğiniz şeylerin diğeri için geçerli olmayabileceğini unutmayın.

Biz o derken (Aynı şekilde, Maybetür vardır * -> *Haskell, biz resmen (saçma olduğu anlamına; gayri biz "bir olması hakkında konuşmak için her zaman) yapmak Maybe." Bunun yerine, bir olabilir Maybe Intya da Maybe Stringbunların şeylerdir çünkü, nazik *.)

Bu nedenle, türlerden bahsetmenin asıl amacı, "sahip" gibi sözcükler hakkındaki akıl yürütmemizi şekillendirebilir ve yalnızca "tamamen inşa edilmiş" ve saçma olmayan türlerin değerlerini almamızı zorunlu kılabiliriz.


1
Analojinizin yanlış olduğunu söylemiyorum ama sanırım karışıklığa neden olabilir. Dijkstra'nın analojiler hakkında bazı kelimeleri vardır. Google "Bilgisayar bilimi öğretmenin zulmünde".
Rafael Castro

Yani, araba analojileri var ve sonra araba analojileri var. Örtük tip yapısını, doğal bir dilde (ki ikinci yarıda da genişlettiğim) biçimsel bir biçim sistemini vurgulamanın, biçimsel bir tip sistemi açıklamanın bir yolu olarak anlatmakla aynı türden bir benzetme olduğunu sanmıyorum. bir program ne yapmak istiyor ".
user11228628

1

Anladığım kadarıyla bir tür bir tür.

Doğru - öyleyse bunun ne anlama geldiğini keşfedelim. Intya da Textbeton türleri vardır, ama Maybe abir bir soyut türü. aBelirli bir değişken için hangi belirli bir değer için (veya değer / ifade / ne olursa olsun) istediğinize karar verene kadar somut bir tür olmayacaktır Maybe Text.

Bunun Maybe abir tür kurucu olduğunu söylüyoruz çünkü tek bir somut tip (örneğin Text) alan ve somut bir tip ( Maybe Textbu durumda) veren bir fonksiyon gibi . Ancak, diğer tip inşaatçılar somut bir tip döndürmeden önce daha fazla “giriş paramları” alabilir. Örneğin , bir somut tip ( ) inşa etmeden önce Map k viki somut tip (örneğin Intve Text) alması gerekir Map Int Text.

Bu nedenle, Maybe ave List atype yapıcılar * -> *(Haskell işlev imzasına benzer şekilde) olarak adlandırdığımız "imzanın" aynısına sahiptir, çünkü onlara bir somut tip verirseniz somut bir tip tükürürler. Biz tipi ve "tür" diyoruz Maybeve Listaynı tür var.

Somut türlerin kibar olduğu söylenir *ve Harita örneğimiz türdür, * -> * -> *çünkü somut bir tür çıktısı vermeden önce girdi olarak iki somut tür alır.

Bunun çoğunlukla tür yapıcıya ilettiğimiz "parametre" sayısıyla ilgili olduğunu görebilirsiniz - ancak tür kurucuların içine yerleştirilmiş olan tür kurucuları da alabileceğimizin farkına varır, böylece * -> (* -> *) -> *örneğin benzeyen bir türle sonuçlanabiliriz .

Eğer bir Scala / Java geliştiricisi iseniz, bu açıklamayı yararlı bulabilirsiniz: https://www.atlassian.com/blog/archives/scala-types-of-a-higher-kind


Bu doğru değil. Haskell, biz ayırt Maybe a, bir eşanlamlısı forall a. Maybe a, tür polimorfik tipini *ve Maybe, türden bir monomorfik türü * -> *.
b0fh
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.