2012-02-15 7 views
52

Sé qué es la covarianza y la contravarianza de los tipos. Mi pregunta es: ¿por qué no me he encontrado con la discusión de estos conceptos todavía en mi estudio de Haskell (en oposición a, digamos, Scala)?¿Por qué no hay muchas discusiones sobre contra y varianza en Haskell (a diferencia de Scala o C#)?

Parece que hay una diferencia fundamental en la forma en que Haskell ve los tipos en comparación con Scala o C#, y me gustaría articular cuál es esa diferencia.

O tal vez estoy equivocado y simplemente no han aprendido lo suficiente Haskell aún :-)

+2

Ha pasado un tiempo, pero parece que recuerdo algún diálogo funcional/haskellish en este video sobre co/contra-varianza: http://channel9.msdn.com/shows/Going+Deep/E2E-Brian-Beckman-and -Erik-Meijer-CoContravariancia-en-Física-y-Programación-2-de-2/ – steamer25

Respuesta

58

Hay dos razones principales:

  • Haskell carece de una noción inherente de subtipos, por lo que, en general, la varianza es menos relevante.
  • La contravariancia aparece principalmente cuando se trata de mutabilidad, por lo que la mayoría de los tipos de datos en Haskell serían simplemente covariantes y habría poco valor para distinguirlos explícitamente.

Sin embargo, los conceptos hacen aplicar - por ejemplo, la operación de elevación realizado por fmap para Functor casos es en realidad covariante; los términos co-/contravariancia se usan en la teoría de categorías para hablar de funtores. El contravariant package define una clase de tipo para funtores contravariantes, y si miras la lista de instancias verás por qué dije que es mucho menos común.

También hay lugares donde la idea aparece implícitamente, en la forma de trabajar manual de conversiones - las distintas clases de tipos numéricos definen las conversiones desde y hacia tipos básicos como Integer y Rational, y el módulo de Data.List contiene versiones genéricas de algunas funciones estándar . Si mira the types of these generic versions, verá que las restricciones Integral (dando toInteger) se utilizan en tipos en posición contravariante, mientras que las restricciones Num (que dan fromInteger) se utilizan para la posición covariante.

+7

No veo relación entre la contravariancia y la mutabilidad. De hecho, la mutabilidad conduce a la invarianza. Los ejemplos de contravarianza son entradas de funciones, 'Ord' y' Eq' (sus equivalentes, por supuesto), ninguno de los cuales tiene datos para ser mutados. –

+13

@ DanielC.Sobral: Escribir en una referencia mutable es contravariante, siendo un caso especial de entrada de función. Entonces, aunque los tipos de datos simples a menudo permiten la covarianza, los tipos que permiten la contravarianza tienden a representar sumideros o productos, que probablemente sean triviales a menos que existan algún tipo de efectos secundarios. Sin embargo, una referencia mutable con operaciones de lectura y escritura es necesariamente invariante. –

+0

@Daniel La contradicción relacionada con la mutabilidad se puede ver en [con la función] (http://hackage.haskell.org/packages/archive/snap/0.7/doc/html/Snap-Snaplet.html#v:with) proporcionada por la API Snaplet de Snap Framework. Fue diseñado precisamente para permitir manipular fácilmente las jerarquías del estado "mutable". – mightybyte

21

No hay "subtipos" en Haskell, por lo que la covarianza y la contravarianza no tienen ningún sentido.

En Scala, usted tiene, por ejemplo, Option[+A] con las subclases Some[+A] y None. Debe proporcionar las anotaciones de covarianza + para decir que Option[Foo] es Option[Bar] si Foo extends Bar. Debido a la presencia de subtipos, esto es necesario.

En Haskell, no hay subtipos. El equivalente de Option en Haskell, llamada Maybe, tiene esta definición:

data Maybe a = Nothing | Just a 

el tipo de variable a tan sólo puede haber un tipo, por lo que no hay más información al respecto es necesario.

6

Como se mencionó, Haskell no tiene subtipos. Sin embargo, si está buscando clases de tipos, puede que no quede claro cómo funciona eso sin subtipificación.

Las clases de tipos especifican los predicados en tipos, no en los tipos. Entonces, cuando una clase de tipo tiene una superclase (por ejemplo, Eq a => Ord a), eso no significa que las instancias sean subtipos, porque solo los predicados se heredan, no los tipos en sí mismos.

También, co, contra y variante significan cosas diferentes en diferentes campos de las matemáticas (ver Wikipedia). Por ejemplo, los términos covariantes y contravariantes se usan en funtores (que a su vez se usan en Haskell), pero los términos significan algo completamente diferente. El término invariante se puede usar en muchos lugares.

Cuestiones relacionadas