2012-02-15 17 views
52

Wiem, jakie są kowariancje i kontrawariancje typów. Moje pytanie brzmi: dlaczego nie spotkałem się jeszcze z omówieniem tych pojęć w moich badaniach nad Haskellem (w przeciwieństwie do Scala)?Dlaczego nie ma wielu dyskusji na temat koincydencji i przeciwności w Haskell (w przeciwieństwie do Scala lub C#)?

Wydaje istnieje zasadnicza różnica w sposobie Haskell Widoki rodzaje w przeciwieństwie do Scala lub C# i chciałbym wyrazić, co to jest różnica.

A może się mylę, a ja po prostu nie nauczyłem się tyle Haskell jeszcze :-)

+2

Minęło trochę czasu, ale wydaje mi się, że pamiętam kilka dialogów funkcjonalno-symfonicznych w tym filmie na temat koherencji/contra-wariancji: http://channel9.msdn.com/shows/Going+Deep/E2E-Brian-Beckman-and -Erik-Meijer-CoContravariance-in-Physics-and-Programming-2-of-2/ – steamer25

Odpowiedz

58

Istnieją dwa główne powody:

  • Haskell brakuje nieodłączną pojęcie podtypy, więc w ogóle wariancja jest mniej istotna.
  • kontrawariancja przeważnie pojawia gdzie zmienność jest zaangażowany, więc większość typów danych w Haskell byłoby po prostu kowariantna i nie byłoby niewiele wartości do rozróżniania jawnie.

Jednak koncepcje zrobić zastosowania - na przykład operacja podnoszenia wykonywane przez fmap dla Functor przypadkach jest rzeczywiście kowariantna; terminy ko-/contrawariancja są używane w teorii kategorii, aby mówić o funktorach. contravariant package definiuje klasę typu dla przeciwwariantnych funktorów, a jeśli spojrzysz na listę instancji, zobaczysz, dlaczego powiedziałem, że jest to mniej powszechne.

Są też miejsca, w których idea pojawia się niejawnie, w jaki sposób obsługi konwersje pracować - różne zajęcia typu liczbowe określenie konwersji do iz podstawowych typów jak Integer i Rational, a moduł Data.List zawiera generycznych niektórych standardowych funkcji . Jeśli spojrzysz na the types of these generic versions zobaczysz, że ograniczenia Integral (podając toInteger) są używane dla typów w pozycji przeciwwstrząsowej, a więzy Num (podając fromInteger) są używane do położenia kowariantnego.

+7

Nie widzę związku pomiędzy sprzecznością a zmiennością. W rzeczywistości zmienność prowadzi do niezmienności. Przykładami sprzeczności są wprowadzane funkcje, "Ord" i "Eq" (ich odpowiedniki, oczywiście), z których żaden nie ma nawet danych do zmutowania. –

+13

@ DanielC.Sobral: Zapisywanie do zmiennego odniesienia jest kontrawariantem, co jest szczególnym przypadkiem wprowadzania funkcji. Tak więc, podczas gdy proste typy danych często pozwalają na kowariancję, typy, które zezwalają na kontrawariancję, mają tendencję do reprezentowania pochłaniaczy lub wyników, które prawdopodobnie będą trywialne, chyba że wystąpią jakieś efekty uboczne. Zmienna referencja z operacjami odczytu i zapisu jest jednak koniecznie niezmienna. –

+0

@Daniel Kontrawariancja związana z zmiennością widoczna jest w [z funkcją] (http://hackage.haskell.org/packages/archive/snap/0.7/doc/html/Snap-Snaplet.html#v:with) pod warunkiem za pomocą Snap Framework's Snaplet API. Został zaprojektowany tak, aby umożliwić łatwą manipulację hierarchiami "zmiennego" stanu. – mightybyte

21

Brak „podtypy” w Haskell, więc kowariancja i kontrawariancja nie ma sensu.

W Scali masz np. Option[+A] z podklasami Some[+A] i None. Musisz podać adnotacje kowariancji + powiedzieć, że Option[Foo] jest Option[Bar] jeśli Foo extends Bar. Ze względu na obecność podtypów jest to konieczne.

W Haskell nie istnieją podtypy. Równowartość Option w Haskell, zwany Maybe, ma tę definicję:

data Maybe a = Nothing | Just a 

Typem zmiennej a może być tylko jeden rodzaj, więc nie ma dalszych informacji o nim jest konieczne.

6

Jak wspomniano, Haskell nie ma podtypy. Jeśli jednak patrzysz na typologie, może nie być jasne, jak to działa bez podtytułów.

Typeklasy określają predykaty typów, a nie same typy. Tak więc, gdy typeclass ma superklasę (np. Eq a => Ord a), nie oznacza to, że instancje są podtypami, ponieważ tylko predykaty są dziedziczone, a nie same typy.

Co-, contra- i in variance oznaczają także różne rzeczy w różnych dziedzinach matematyki (patrz Wikipedia). Na przykład terminy kowariancyjny i contrawariant są używane w funktorach (które z kolei są używane w Haskell), ale terminy oznaczają coś zupełnie innego. Termin niezmiennik może być używany w wielu miejscach.