2012-05-24 7 views
11

Programowałem w języku C#, ale byłem sfrustrowany ograniczeniami jego systemu typów. Jedną z pierwszych rzeczy, dowiedziałem się o Scali było to, że Scala ma wyższe rodzaje genów. Ale nawet gdy przyjrzałem się kilku artykułom, wpisom na blogu i pytaniom, wciąż nie byłem pewien, jakie są wyższe rodzaje genów. W każdym razie napisałem trochę kodu Scala, który kompilował dobrze, Czy ten fragment używa wyższych rodzajów?Scala: Wyższe rodzajowe, otwarte i dzikie karty genowe w Javie, C#, Scala i C++

abstract class Descrip [T <: DTypes, GeomT[_ <: DTypes] <: GeomBase[_]](newGeom: NewGeom[GeomT]) 
{ 
    type GeomType = GeomT[T] 
    val geomM: GeomT[T] = newGeom.apply[T]() 
} 

A potem pomyślałem, że może już używam wyższych rodzajów leków. Tak jak ja to rozumiem, ale teraz, jak to teraz rozumiem, z przyjemnością korzystałem z wyższych typów w języku C#, zanim usłyszałem o Scali. Czy ten snipet używa wyższej jakości typu?

namespace ConsoleApplication3 
{ 
    class Class1<T> 
    { 
     List<List<T>> listlist; 
    } 
} 

Tak, aby uniknąć dalszych nieporozumień myślałem byłoby wyjaśnienie dla każdego Java, C# i Scala co pozwalają one pod względem Higher kinded typy, dzikie karty i korzystania z otwartych/częściowo otwartych typów. Ponieważ kluczową różnicą między C# i Scala wydaje się być to, że Scala zezwala na dzikie karty i typy otwarte, gdzie jako C# nie ma żadnej dzikiej karty i wymaga, aby wszystkie typy ogólne zostały zamknięte przed użyciem. Wiem, że są one różne, ale myślę, że byłoby użyteczne powiązanie istnienia tych funkcji z ich odpowiednikami w C++ Templates.

Tak jest następujące prawidłowe? Tabela ta została skorygowana dla Aleksieja odpowiedź

Lang: Higher-kind Wild-card Open-types 

Scala yes   yes  yes 

C#  no   no  no 

Java  no   yes  no 

C++  yes   yes  yes 
+3

Jakie jest twoje pytanie? –

+0

Czy tabela na dole jest poprawna? Jeśli ktokolwiek może to sformatować lepiej, zrób to? –

+0

To, co napisałeś w języku C#, jest dostępne w języku java, a nie w wersji wyższej. Twoja klasa z powyższym parametrem GeomT jest. Zobacz http://stackoverflow.com/a/10499788/754787. –

Odpowiedz

9

ten jest wyższy rodzaj kinded to go nie:

nr Wyższy-kinded typ jest coś

class Class1<T> 
{ 
    T<String> foo; // won't compile in actual C# 
} 

To znaczy rodzaj ogólny, którego parametry muszą być same w sobie generyczne. Zauważ, że w tym przykładzie powinien się kompilować Class1<IList>, ale Class1<String> lub Class1<IDictionary> nie powinien.

+0

Ah w końcu myślę, że widzę. –

8

Wygląda na to, że musisz zrozumieć, czym są wyższe typy i dlaczego są przydatne.

Rozważmy następujące interfejsy (Java, F<X,Y> stosowane jako zamiennik zamknięcia):

interface ListFun { 
    public <A,B> List<B> fmap(F<A,B> fn, List<A> list); 
} 

interface SetFun { 
    public <A,B> Set<B> fmap(F<A,B> fn, Set<A> set); 
} 

Interfejsy wyglądać przydatna, ponieważ określają rodzaj „transformacji” dla zbiorów (nazywa się to „funktor”) . Ale wyglądają podobnie do powielania kodu. Ale nie można napisać "zunifikowanego" interfejsu, ani w Javie, ani w C#.

Jak powinien wyglądać? Byłbyś kuszony napisać coś podobnego

interface Fun<X> { 
    public <A,B> X<B> fmap(F<A,B> fn, X<A> col); 
} 

class ListFun implements Fun<List> {...} 

Ale X<A> nie jest dozwolony w Java lub C#, jeśli X nie jest stałym typu jak List, ale parametr typ. Ale jeśli ta abstrakcja jest w jakiś sposób dozwolona (tak jak w Scali czy Haskell), masz wyższe rodzaje typów (lub "polimorfizm typu wyższego rzędu", terminologia jest nadal mętna).Oto cecha Scala i implementacja:

trait Fun[X[_]] { 
    def fmap[A,B](fn: A => B, col:X[A]):X[B] 
} 

class ListFun extends Fun[List]{ 
    def fmap[A,B](fn: A => B, list: List[A]) = list.map(fn) 
} 

To jest podstawowa idea. Zwykle nie potrzebujesz tego zbyt często, ale gdy potrzebujesz tego, może być niesamowicie użyteczny.

+0

Odświeżające porównanie z java i C# dotyczące parametrów typu, dzięki! –