Почему в Haskell нет много дискуссий о совпадении и противоречивости (в отличие от Scala или С#)?
Я знаю, что такое ковариация и контравариантность типов. Мой вопрос: почему я не столкнулся с обсуждением этих понятий еще в моем исследовании Haskell (в отличие от, скажем, Scala)?
Кажется, существует фундаментальное различие в том, как Haskell рассматривает типы в отличие от Scala или С#, и я хотел бы сформулировать, что это за разница.
Или, может быть, я ошибаюсь, и я еще недостаточно изучил Haskell: -)
Ответы
Ответ 1
Существуют две основные причины:
- Haskell не имеет неотъемлемого понятия подтипирования, поэтому в целом дисперсия менее актуальна.
- Контравариантность в основном появляется там, где задействована мутация, поэтому большинство типов данных в Haskell просто были бы ковариантными, и было бы мало смысла выделять это явно.
Однако эти концепции применимы - например, операция подъема, выполняемая экземплярами fmap
для Functor
, фактически ковариантна; термины co-/contravariance используются в Теории Теории, чтобы говорить о функторах. Пакет contravariant
определяет класс типа для контравариантных функторов, и если вы посмотрите на список экземпляров, вы поймете, почему я сказал это намного меньше общее.
Существуют также места, где идея проявляется неявно в том, как работают ручные преобразования - различные классы числового типа определяют преобразования и из основных типов, таких как Integer
и Rational
, а модуль Data.List
содержит общие версии некоторых стандартных функций. Если вы посмотрите на типы этих общих версий, вы увидите, что ограничения Integral
(предоставление toInteger
) используются для типов в контравариантных, в то время как ограничения Num
(предоставление fromInteger
) используются для ковариантной позиции.
Ответ 2
В Haskell нет "подтипов", поэтому ковариация и контравариантность не имеют никакого смысла.
В Scala у вас есть, например, Option[+A]
с подклассами Some[+A]
и None
. Вы должны предоставить аннотации ковариации +
, чтобы сказать, что Option[Foo]
является Option[Bar]
, если Foo extends Bar
. Из-за наличия подтипов это необходимо.
В Haskell нет подтипов. Эквивалент Option
в Haskell, называемый Maybe
, имеет это определение:
data Maybe a = Nothing | Just a
Тип переменной a
может быть только одним типом, поэтому дополнительная информация о ней не требуется.
Ответ 3
Как уже упоминалось, у Haskell нет подтипов. Однако, если вы смотрите на классные классы, может быть неясно, как это работает без подтипирования.
Typeclasses задают предикаты по типам, а не самим типам. Поэтому, когда Typeclass имеет суперкласс (например, Eq a = > Ord a), это не означает, что экземпляры являются подтипами, поскольку наследуются только предикаты, а не сами типы.
Кроме того, ко-, противопоставление и инвариантность означают разные вещи в разных областях математики (см. Википедию). Например, члены, ковариантные и контравариантные, используются в функторах (которые, в свою очередь, используются в Haskell), но термины означают нечто совершенно иное. Термин "инвариант" можно использовать во многих местах.