В чем разница между A или Int Int? Что такое Ли? Конструктор полиморфного типа? В чем его цель?

Введение

Я понимаю разницу между Maybe a и Maybe Int, я также понимаю разницу между Either a b и Either Int Int. Я также понимаю, что Either Int является тем же самым видом животных, что и Maybe, оба они берут тип в качестве аргумента и создают новый тип, т.е. Они являются конструкторами типа, которые принимают один тип как параметр (либо конкретный, как Int или а не бетона типа a) и производить либо конкретный тип, либо полиморфный тип.

Теперь, что я не понимаю, какова конструкция Either a? Это не похоже на Maybe, потому что он никогда не сможет создать конкретный (читаемый не полиморфный) тип, если мы будем подсылать ему конкретный тип (например, Int). Поэтому в этом случае правильно ли вызывать Either a конструктор полиморфного типа и вызывать Maybe конструктор конкретного типа? (Это как я их называю, каково их официальное название в номенклатуре Haskell?)

Кроме того, я не знаю, что такое официальная классификация в системе типа Haskell конструкторов типа типа Either a, потому что она не может быть в той же категории, что и Maybe, потому что, как упоминалось в предыдущем абзаце, независимо от того, какой тип мы применяем Either a, результирующий тип никогда не будет конкретным типом, т.е. он всегда будет полиморфным типом, например Either a Int.

Причина, по которой я спрашиваю об этом, состоит в том, что Either a является Functor. Что начинает запутываться. Ничего похожего на то, что я видел раньше. Я не знаю, как я должен концептуально интерпретировать тот факт, что Either a (конструктор полиморфного типа) является экземпляром Functor? Аналогично, (->) r (который также является тем же самым видом животных, что и Either a) также является Functor.

Вопросы:

Что такое Either a и (->) r?

Что они называли официально?

Как они концептуально вписываются в систему типов Haskell?

Где эти конструкторы полиморфного типа описаны/обсуждены более подробно?

Чему бы я читал, поэтому я лучше понимаю их?

Должен ли я читать о видах? Являются ли виды секретным способом понимания таких конструкторов полиморфного типа как Either a и (->) r?

Является ли Either a Int тем же видом животных, что и [a]?

Единственная цель Either a Int объявить полиморфные типы ввода и вывода для функций, как и в случае [a] в fmap :: (a -> b) -> [a] -> [b]?

Самый важный вопрос:

Как я должен интерпретировать следующий код в свете описанных выше мыслей?

instance Functor (Either a) where 
  fmap f (Right x) = Right (f x) 
  fmap f (Left x) = Left x

class Functor f where 
  fmap :: (a -> b) -> f a -> f b

Таким образом, результирующая функция fmap (тип которой fmap :: (a -> b) -> Either c a -> Either c b) будет полиморфна в c?

Это единственный эффект от создания Either a экземпляра Functor? Так что результирующая функция fmap будет полиморфна в c?

По сравнению с, например, делая Either Int экземпляр Functor?

Тогда полученный fmap будет работать только на типах Either Int a, но не будет работать вообще/полиморфно на всех типах Either a b?

Если я правильно понимаю, это единственная точка и цель создания конструкторов полиморфного типа типа Either a? Итак, fmap работает со всеми типами Either a b?

Я смущен, и я не уверен, правильно ли я интерпретирую Either a. Может кто-нибудь, пожалуйста, подтвердите, что 1) либо моя интерпретация верна 2) если нет, тогда, пожалуйста, просветите меня.

Спасибо за чтение.

Ответ 1

Maybe не является типом. Maybe Int - это тип. Но Maybe, само по себе, это то, из чего вы можете сделать тип. Это функция конструктора типов.

Either не является типом, это конструктор типа. Вы знаете, как вы можете выполнять функции Haskell? Ну, вы можете также использовать функции конструктора типов. Таким образом, Either - это функция конструктора типа 2 аргумента, но Either Int является конструктором типа 1 аргумента. И Either Int Bool является фактическим типом.

Класс типа Functor - это класс более высокого класса. Что-то вроде Show относится к типу; Functor применяется к конструктору типа. Например, вы не пишете

instance Functor (Maybe Int) where ...

Вместо этого вы пишете

instance Functor (Maybe) where ...

Определение Functor есть

class Functor f where
  fmap :: (x -> y) -> f x -> f y

Здесь f не тип, а функция конструктора типа 1 аргумента. Вы даете ему аргумент (например, x или y) для создания реального, пригодного для использования типа.

Значения имеют "типы". Вещи в сигнатуре типа имеют "виды". "Тип" имеет вид *. Конструктор типа "1-аргумент" имеет вид "* → *". В основном это говорит о том, сколько аргументов вы должны предоставить для получения фактического типа.

В заключение вы можете написать экземпляр для Functor (Either Int). Но тогда допускается только Int; сделав его переменной типа, вы сделаете его более полиморфным.

Обратите внимание, что если вы этого хотели, чтобы второй аргумент Either был исправлен, а не первый, вы не можете этого сделать. В некотором смысле более высокоподобные классы типа - это немного клочья. Это их просто понять, и они работают для простых случаев. Функциональные зависимости и связанные типы - это две (несовместимые) попытки решить эту проблему лучше.

Ответ 2

Нет такой вещи, как Either a. Подобно полиморфным функциям, полиморфные экземпляры должны считываться в стиле system-F с универсальной квантификацией:

forall a . instance Functor (Either a) where ...

Сам экземпляр-функтор - это словарь, то есть функция уровня типа

functor = Λf -> { Λa b -> (a->b) -> f a->f b }

Таким образом, любой экземпляр будет выглядеть как

eitherFunctor = Λa -> functor (Either a)

В качестве альтернативы вы можете думать об этом, как если бы компилятор заменил instance Functor (Either a) на количество дискретных экземпляров

instance Functor (Either ()) where ...
instance Functor (Either Int) where ...
...
instance Functor (Either (Either Int String)) where ...
...

Хотя это, очевидно, не удастся сделать это буквально.

Ответ 3

Я не знаю ответов на некоторые из ваших вопросов - например, что-то называется официально или где их читать, потому что они выглядят само собой разумеющимися после изучения систем типов. (Это не следует воспринимать как совет, что единственный способ получить неподходящий - пойти на изучение зависимых систем типов.)

Either Int также может быть объявлен как Functor, но мы можем выразить более общее утверждение, что на самом деле не имеет значения, является ли первый аргумент Either Int - поэтому мы объявляем, что Either a является Functor.

В системах другого типа нет необходимости различать kinds, вместо этого Either можно рассматривать как тип; но в Haskell они обрабатываются отдельно от типов, чтобы упростить систему типов. kinds - это способ описать, что типы имеют арность и избегают осложнений с зависимыми типами, только различая arity. Итак, Either и (->) имеют arity 2, или kind *->*->*.

Either a Int является тем же самым животным, что и [a] в том смысле, что их вид *.

fmap :: (a->b) -> Either c a -> Either c b является действительно полиморфным в c. Важность этого заявления заключается в том, что он сохраняет c. Конечно, единственный способ, который может произойти для любого типа c, - это когда Left x остается нетронутым.