Можно ли рассматривать конструкторы типов как типы в функциональных языках программирования? - PullRequest
0 голосов
/ 10 февраля 2019

Я приближаюсь к языку программирования Haskell, и у меня есть опыт работы с Scala и Java-разработчиком.

Я читал теорию, лежащую в основе конструкторов типов, но я не могу понять, могут ли они рассматриваться как типы.Я имею в виду, что в Scala вы используете ключевые слова class или trait для определения конструкторов типов.Подумайте о List[T] или Option[T].Также в Haskell вы используете то же ключевое слово data, которое используется для определения новых типов.

Итак, конструкторы типов также являются типами?

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

Давайте посмотрим на аналогию: функции.В некоторых разделах математики функции называются конструкторами значений , потому что это то, что они делают: вы помещаете одно или несколько значений, и они создают новое значение из этих.

Конструкторы типовэто одно и то же, за исключением уровня типов: вы помещаете один или несколько типов, и они создают из них новый тип.В некотором смысле они являются функциями на уровне типов.

Теперь, по нашей аналогии: каков аналог вопроса, который вы задаете?Что ж, это так: «Могут ли конструкторы значений (т.е. функции) рассматриваться как значения в функциональных языках программирования?»

И ответ таков: это зависит от языка программирования.Теперь для функциональных языков программирования ответ «Да» почти для всех (если не для всех) из них.Это зависит от вашего определения, что такое «функциональный язык программирования».Некоторые люди определяют функциональный язык программирования как язык программирования, который имеет функции в качестве значений, поэтому ответ будет тривиально «Да» по определению.Но некоторые люди определяют функциональный язык программирования как язык программирования, который не допускает побочных эффектов, и на таком языке не обязательно верно, что функции являются значениями.

Самым известным примером может быть ДжонFP Бэкуса, из его оригинальной статьи Можно ли освободить программирование от стиля фон Неймана?- функциональный стиль и его алгебра программ .В FP есть иерархия «функциональных» вещей.Функции могут иметь дело только со значениями, а сами функции не являются значениями.Однако существует понятие «функционалы», которые являются «конструкторами функций», то есть они могут принимать функции (и также значения) в качестве входных данных и / или создавать функции в качестве выходных данных, но они не могут принимать функционалы в качестве входных данных и / или создавать их какoutput.

Итак, FP, возможно, является функциональным языком программирования, но он не имеет функций в качестве значений.

Примечание: функции в качестве значений также называются «функциями первого класса» и функциями, которыепринимать функции в качестве входных данных или возвращать их в качестве выходных, называются «функциями более высокого порядка».

Если мы рассмотрим некоторые типы:

1   :: Int
[1] :: List Int
add :: Int → Int
map :: (a → b, List a) → b

Вы можете видеть, что мы можем легко сказать: любойзначение, тип которого содержит стрелку, является функцией.Любое значение, тип которого содержит более одной стрелки, является функцией более высокого порядка.

Опять-таки, то же самое относится и к конструкторам типов, поскольку они действительно одно и то же, за исключением уровня типа.В некоторых языках конструкторы типов могут быть типами, в некоторых - нет.Например, в Java и C♯ конструкторы типов не являются типами.Например, у вас не может быть List<List> в C♯.Вы можете записать тип List<List> в Java, но это вводит в заблуждение, поскольку два List означают разные вещи: первый List является конструктором типа, второй List является необработанный тип , так что на самом деле не использует конструктор типа в качестве типа.

Что эквивалентно нашему примеру типов выше?

Int     :: Type
List    :: Type ⇒ Type
→       :: (Type, Type) ⇒ Type
Functor :: (Type ⇒ Type) ⇒ Type

(Обратите внимание, как у нас всегда есть Type? Действительно, мы имеем дело только с типами, поэтому обычно мы не пишем Type, а вместо этого просто пишем *, произносится "Тип"):

Int     :: *
List    :: * ⇒ *
→       :: (*, *) ⇒ *
Functor :: (* ⇒ *) ⇒ *

Итак, Int - правильный тип, List - конструктор типов, который принимает один тип и создает тип, (конструктор типа функции) принимает два типа и возвращает тип(предполагая только унарные функции, например, используя каррирование или передачу кортежей), и Functor является конструктором типов, который сам принимает конструктор типов и возвращает тип.

Тезисы "type-types" называются виды .Как и в случае с функциями, все, что имеет стрелку, является конструктором типа, а все, что содержит более одной стрелки, является конструктором высшего рода .

AКак и в случае с функциями, некоторые языки допускают конструкторы типов с более высоким родом, а некоторые - нет.Два языка, которые вы упоминаете в своем вопросе: Scala и Haskell do , но, как уже упоминалось выше, Java и C♯ не делают.вопрос:

Итак, конструкторы типов также являются типами?

Не совсем, нет.По крайней мере, не на любом языке, о котором я знаю.Видите, хотя у вас могут быть конструкторы типов с более высоким родом, которые принимают конструкторы типов в качестве входных данных и / или возвращают их в качестве выходных данных, вы не можете иметь выражение или значение, или переменную, или параметр, у которого в качестве типа используется конструктор типа.Вы не можете иметь функцию, которая принимает List или возвращает List.Вы не можете иметь переменную типа Monad.Но вы можете иметь переменную типа Int.

Итак, очевидно, что между типами и конструкторами типов есть разница.

0 голосов
/ 11 февраля 2019

По крайней мере, в Haskell существует иерархия, которую можно приблизительно описать следующим образом:

Термины - это вещи, которые существуют во время выполнения, такие значения, как 1, 'a' и (+), например.

Каждый член имеет тип , например Int или Char или Int -> Int -> Int.

Каждый тип имеет вид , ивсе типы имеют одинаковый тип, а именно *.

Конструктор типа, такой как [], имеет тип * -> *, поэтому он не является типом.Вместо этого это отображение от типа к типу.


Есть и другие виды, в том числе (в дополнение к * и * -> *, спример каждого):

  • * -> * -> * (Either)
  • (* -> *) -> * -> * (ReaderT, монадный трансформатор)
  • Constraint (Num Int)
  • * -> Constraint (Num; это тип класса)
0 голосов
/ 11 февраля 2019

Ну, у типов и конструкторов типов есть свое исчисление, и у каждого из них есть виды.Например, если вы используете :k (Maybe Int) в ghci, вы получите *, теперь это правильный тип, и у него ( обычно ) есть жители.В этом случае Nothing, Just 42 и т. Д. * теперь имеет более описательный псевдоним Type.

Теперь вы можете посмотреть на тип конструктора Maybe и :k Maybe даст вам * -> *.С псевдонимом это Type -> Type, что вы ожидаете.Требуется Type и конструкции a Type.Теперь, если вы видите типы как набор значений, один хороший вопрос: какой набор значений имеет Maybe?Ну, нет, потому что это не совсем тип.Вы можете попробовать что-то вроде Just, но с типом a -> Maybe a с видом Type, а не с Maybe с видом Type -> Type.

...