Haskell'in tür sistemi resmen Java'lara denk mi? [kapalı]


66

Bazı şeylerin bir dilde diğerinden daha kolay / daha zor olduğunun farkındayım, ancak yalnızca bir tanesinde mümkün olan ve diğerinde imkansız / alakasız türlerle ilgili özelliklerle ilgileniyorum. Daha belirgin hale getirmek için, Haskell tipi uzantıları görmezden gelelim, çünkü orada her türlü çılgın / havalı şeyi yapan çok insan var.


4
Uzun soluklu kategori teorisyenlerinin bu soruya cevap verdiğini duymayı da merak ediyorum; Özellikle anlayacağımdan şüphelenmeme rağmen, bunun ayrıntılarıyla ilgilenmeye devam ediyorum. Okuduğum şeylerden kaynaklanan eğilimim, HM tipi sistemin derleyicinin kodunuzun ne yaptığı hakkında bir ton bilgisine sahip olmasına izin vermesidir, bu yüzden davranışları hakkında çok fazla garanti vermenin yanı sıra bu kadar çok tip çıkarımına da sahiptir. Ama bu sadece içgüdülerim içgüdüsü ve kesinlikle bilmediğim başka şeyler olduğuna eminim.
Jimmy Hoffa,

1
Bu harika bir soru - büyük Haskell / JVM tartışması için takipçilerine tweet atma zamanı!
Martijn Verburg

6
@ m3th0dman: Scala, Java'daki gibi üst düzey işlevler için tam olarak aynı desteğe sahip. Scala'da birinci sınıf işlevler, Java gibi, tek bir soyut yöntemle soyut sınıf örnekleri olarak temsil edilir. Tabii ki, Scala bu fonksiyonları tanımlamak için sözdizimsel bir şekere sahiptir ve hem fonksiyonları önceden tanımlanmış hem de fonksiyonları kabul eden yöntemlerden oluşan zengin bir standart kütüphaneye sahiptir, ancak bu sorunun ne olduğu ile ilgili bir tür sistem perspektifinden hiçbir fark yoktur. . Öyleyse eğer Scala başarabilirse, Java da yapabilir ve aslında Java için Haskell'den esinlenmiş FP kütüphaneleri vardır.
Jörg W Mittag

2
@ m3th0dman: Bu sorunun konusu bu değil.
Phil

7
@ m3th0dman Mükemmel sıradan tipler. Bazı synactic kibarlıkların dışında listelerde özel bir şey yok. Hazır bilgi sözdizimi ve yapıcıların adları dışında, yerleşik liste türüne eşdeğer olan kendi cebirsel veri türünüzü kolayca tanımlayabilirsiniz.
sepp2k

Yanıtlar:


63

(Burada kullanılan "Java", standart Java SE 7 olarak tanımlanmıştır ; "Haskell", burada kullanıldığı gibi, Haskell 2010 standardı olarak tanımlanmaktadır .)

Java'nın tip sisteminin sahip olduğu ancak Haskell'in yapmadığı şeyler:

  • nominal alt tip polimorfizmi
  • kısmi çalışma zamanı türü bilgisi

Haskell'in tip sisteminin sahip olduğu fakat Java'nın yapmadığı şeyler:

  • sınırlı geçici polimorfizm
    • "kısıtlamaya dayalı" alt tip polimorfizmine yol açar
  • yüksek tür parametrik polimorfizm
  • asıl yazma

DÜZENLE:

Yukarıda listelenen noktaların her birine örnekler:

Java'ya özgü (Haskell ile karşılaştırıldığında)

Nominal alt tip polimorfizmi

/* declare explicit subtypes (limited multiple inheritance is allowed) */
abstract class MyList extends AbstractList<String> implements RandomAccess {

    /* specify a type's additional initialization requirements */
    public MyList(elem1: String) {
        super() /* explicit call to a supertype's implementation */
        this.add(elem1) /* might be overridden in a subtype of this type */
    }

}

/* use a type as one of its supertypes (implicit upcasting) */
List<String> l = new ArrayList<>() /* some inference is available for generics */

Kısmi çalışma zamanı türü bilgisi

/* find the outermost actual type of a value at runtime */
Class<?> c = l.getClass // will be 'java.util.ArrayList'

/* query the relationship between runtime and compile-time types */
Boolean b = l instanceOf MyList // will be 'false'

Haskell'e özgü (Java ile karşılaştırıldığında)

Sınırlı özel polimorfizm

-- declare a parametrized bound
class A t where
  -- provide a function via this bound
  tInt :: t Int
  -- require other bounds within the functions provided by this bound
  mtInt :: Monad m => m (t Int)
  mtInt = return tInt -- define bound-provided functions via other bound-provided functions

-- fullfill a bound
instance A Maybe where
  tInt = Just 5
  mtInt = return Nothing -- override defaults

-- require exactly the bounds you need (ideally)
tString :: (Functor t, A t) => t String
tString = fmap show tInt -- use bounds that are implied by a concrete type (e.g., "Show Int")

"Sınırlamaya dayalı" alt tip polimorfizmi (sınırlı geçici polimorfizme dayalı)

-- declare that a bound implies other bounds (introduce a subbound)
class (A t, Applicative t) => B t where -- bounds don't have to provide functions

-- use multiple bounds (intersection types in the context, union types in the full type)
mtString :: (Monad m, B t) => m (t String)
mtString = return mtInt -- use a bound that is implied by another bound (implicit upcasting)

optString :: Maybe String
optString = join mtString -- full types are contravariant in their contexts

Yüksek tür parametrik polimorfizm

-- parametrize types over type variables that are themselves parametrized
data OneOrTwoTs t x = OneVariableT (t x) | TwoFixedTs (t Int) (t String)

-- bounds can be higher-kinded, too
class MonadStrip s where
  -- use arbitrarily nested higher-kinded type variables
  strip :: (Monad m, MonadTrans t) => s t m a -> t m a -> m a

Ana yazma

Bunun doğrudan bir örneğini vermek zordur, ancak bu, her ifadenin, ifadenin kanonik türü olarak kabul edilen tam olarak bir maksimum genel türüne ( asıl türü denir ) sahip olduğu anlamına gelir . "Sınırlamaya dayalı" alt tip polimorfizmi (yukarıya bakınız) açısından, bir ifadenin temel türü, ifadenin kullanılabileceği her olası türün benzersiz alt türüdür. Asıl yazmanın varlığı (eksiz) Haskell, tam tür çıkarımına izin veren şeydir (yani, herhangi bir tür açıklama gerektirmeden her ifade için başarılı tür çıkarımı). Asıl yazmayı bozan uzantılar (birçoğu vardır), aynı zamanda tür çıkarımının bütünlüğünü de bozar.


7
lTek harfli değişken olarak kullanmayın , ayırt etmek ÇOK zor 1!
recursion.ninja

5
Java'nın bazı çalışma zamanı türü bilgisine sahip olduğundan ve Haskell'in kesinlikle haklı olmasına rağmen, birçok tür için çalışma zamanı türü bilgisi gibi davranan bir şey sağlamak için Haskell'deki Tipik tür sınıfını kullanabilirsiniz (daha yeni PolyKinded ile). sınıflar yoldayken, her şey iirc olacaktır), her ne kadar çalışma zamanında herhangi bir tür bilgiyi geçirip geçirmemesi durumuna bağlı olduğunu düşünüyorum.

3
@DarkOtter Farkındayım Typeable, ancak Haskell 2010 buna sahip değil (belki Haskell 2014 olacak?).
Ptharien'ın Alevi

5
(Kapalı) toplam türleri hakkında ne? Kısıtlamaları kodlamanın en önemli mekanizmalarından biridir.
tibbe,

3
Nullability? Sağlamlık (kovaryans yokilini yok)? Kapalı toplam tipleri / desen eşleşmeleri? Bu cevap çok dar
Peaker

32

Java'nın tip sistemi daha yüksek tür polimorfizmine sahip değildir; Haskell'in tipi sistemi var.

Başka bir deyişle: Java'da, yazı kurucuları türler üzerinde soyutlayabilirler, ancak yazı kurucuları üzerinde soyutlayamazlar, oysa Haskell'de yazı kurucular, yazı tiplerinin yanı sıra yazı tiplerini de soyutlayabilirler.

İngilizce'de: Java'da bir jenerik başka bir jenerik tipe giremez ve onu parametreleyemez,

public void <Foo> nonsense(Foo<Integer> i, Foo<String> j)

Haskell'de bu oldukça kolay

higherKinded :: Functor f => f Int -> f String
higherKinded = fmap show

28
Bu sefer yine İngilizce olarak mı aklımıza geliyor? : P
Mason Wheeler

8
@Matt: Örnek olarak, bunu Java ile yazamıyorum, ancak eşdeğerini Haskell: 'de yazabiliyorum <T<_> extends Collection> T<Integer> convertStringsToInts(T<string> strings). Buradaki fikir, eğer birileri onu convertStringsToInts<ArrayList>bir dizgenin arilistini alıp bir tamsayı aretrisini geri getirecek şekilde çağırırsa olacaktır. Ve bunun yerine kullanılırsa convertStringsToInts<LinkedList>, bunun yerine bağlantılı listelerle aynı olurdu.
sepp2k

8
Bu yüksek tür polimorfizm değil, rütbe 1 yerine n değil mi?
Adam,

8
@ JörgWMittag: Benim anlayışım, yüksek rütbeli polimorfizm foralltürlerini nereye koyabileceğinizle ilgilidir . Haskell'de bir tür a -> börtük olarak forall a. forall b. a -> b. Bir uzantıyla, forallbunları açık hale getirebilir ve etrafta dolaştırabilirsiniz.
Tikhon Jelvis 9:12

8
@Adam sağlam: yüksek rütbe ve yüksek rütbeli tamamen farklı. GHC, bazı dil uzantılarıyla daha yüksek dereceli türleri (örneğin forall türleri) de yapabilir. Java, ne yüksek tür ne de yüksek dereceli türler olduğunu bilir.
Ingo

11

Diğer cevapları tamamlamak için, Haskell'in tür sistemi alt yazarken, Java gibi nesne yönelimli dilleri de yazmaz .

Olarak programlama dili teori , alt-tiplemesi (aynı zamanda polimorfizm alt tip veya dahil polimorfizm şeklidir) tipi polimorfizmi bir hangi alt tipi a, veri türü bir veri türü (ilgilidir süper tip bazı nosyonu ile) ikame edilebilirlik , tipik olarak alt rutin, bu program elemanları, yani veya üst tipin elemanları üzerinde çalışmak üzere yazılan fonksiyonlar alt tipin elemanları üzerinde de çalışabilir. Eğer S, T'nin bir alt tipi ise, alt-ilişki ilişkisi genellikle S tipinin herhangi bir bağlamında güvenli bir şekilde kullanılabileceği anlamına gelir.T tipi bir terim bekleniyor. Alt yazı yazmanın kesin anlamsal önemi, belirli bir programlama dilinde "güvenli bir şekilde kullanılan" anlamındadır. Tür sistemi bir programlama dilinin esasen iyi önemsiz olabilir, kendi alt-tiplemesi ilişkisini tanımlar.

Alt ilişkilendirme nedeniyle, bir terim birden fazla türe ait olabilir. Subtyping bu nedenle bir tür polimorfizm şeklidir. Nesneye yönelik programlamada, "polimorfizm" terimi, genellikle bu alt tip polimorfizmine atıfta bulunmak için kullanılırken, parametrik polimorfizm teknikleri genel programlama olarak kabul edilir ...


4
Bu, geçici polimorfizm elde edemeyeceğiniz anlamına gelmez. Siz sadece farklı bir formda (alt tip polimorfizmi yerine tip sınıfları).

3
Alt sınıflama alt türleme değil!
Frank Shearar

8

Şu ana kadar kimsenin bahsetmediği bir şey, tür çıkarımı: Haskell derleyicisi genellikle ifadelerin türünü çıkartabilir, ancak Java derleyicisine türlerinizi ayrıntılı olarak anlatmanız gerekir. Kesinlikle, bu derleyicinin bir özelliğidir, ancak dil ve tür sisteminin tasarımı, tür çıkarımının mümkün olup olmadığını belirler. Özellikle, tür çıkarımı, Java'nın alt tipi polimorfizmiyle ve geçici aşırı yüklenmeyle kötü etkileşime girer. Buna karşılık, Haskell'in tasarımcıları, tür çıkarımını etkileyen özellikler eklememeye çalışmaktadırlar.

İnsanların şu ana kadar bahsetmedikleri bir başka şey cebirsel veri türleridir. Yani, toplamlardan ('veya') ve diğer tipteki ürünlerden ('ve') türler oluşturma yeteneği. Java sınıfları ürünleri (alan a ve alan b, demek) iyi yapıyor. Fakat gerçekten toplamları yapmazlar (alan bir VEYA alan b, örneğin). Scala, bunu tamamen aynı olmayan çoklu vaka sınıfları olarak kodlamak zorunda. Ve Scala için çalışırken, Java'da olduğunu söylemek biraz zor.

Haskell ayrıca, -> işlev yapıcısını kullanarak işlev türlerini de oluşturabilir. Java'nın yöntemleri tür imzalarına sahip olsa da bunları birleştiremezsiniz.

Java'nın tür sistemi, Haskell'in sahip olmadığı bir tür modülerliği mümkün kılıyor. Haskell için bir OSGi olmadan bir süre önce olacak.


1
@ MattFenwick, geribildiriminize dayanarak 3. paragrafı değiştirdim. İki tip sistem fonksiyonları çok farklı şekilde ele alıyor.
GarethR

ADT'leri tip sisteminin bir özelliği olarak görmezdim. Onları tamamen (beceriksizce) OO sarmalayıcılarıyla taklit edebilirsiniz.
leftaroundabout

@leftaroundabout Bu tartışmalı olduğunu düşünüyorum. Örneğin, bir dilin tip sistemine özgü olan, ancak diğerinde tasarım desenleriyle uygulanabilecek şeyler olabilir. Açıkçası, tasarım deseni yolu, yerel olana kıyasla, bir geçici çözümdür. Daha zayıf bir tür sistem nedeniyle geçici çözüm.
Hi-Angel,

Seçilen cevap, 'Asıl Yazma' bölümünde 'tam tip çıkarım' dan bahsetti. Java, alt türler ve çalışma zamanı türü bilgileriyle öykünme toplamlarını sıralayabilir, ancak sizin dediğiniz gibi, toplamın tür sisteminin bütünsel bir niteliği olmadığı gibi değildir.
Shelby Moore III
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.