Пример функции уровня типа, которая не является конструктором типа - PullRequest
0 голосов
/ 26 августа 2018

Что является уникальным для концепции "конструктора типов" в Haskell по сравнению с другими функциями уровня типа?

Насколько я знаю, они:

  • позволяет пользователю применять аргументы к ним во время компиляции
  • приводит к простому типу (например, не к ограничению) после предоставления конечного числа аргументов

1 Ответ

0 голосов
/ 26 августа 2018

Фраза «конструктор типов» употребляется двумя способами. Некоторые люди используют их для любого типа со стрелкой; но в отчете на Haskell он довольно последовательно используется по-другому, поэтому я поговорю об этом определении.

Конструкторы создаются объявлениями data и newtype и являются единственным новым именем, введенным этими уровнями на уровне типа. Вот несколько примеров конструкторов типов:

Either
Maybe
[]
Bool

Упс, вы заметили этот последний? Правильно, в фразе «конструктор типов» нет ничего, что подразумевало бы, что она должна иметь возможность принимать аргументы. Bool - это имя уровня типа, введенное объявлением данных - следовательно, является конструктором типа. Вот несколько примеров типов, которые не являются конструкторами:

Maybe Int
a -> b
Either ()
m -- even if we know, say, Monad m holds

Упс, вы заметили эти последние два? Правильно, если идти в другом направлении, нет ничего в том, чтобы иметь возможность принимать дополнительные аргументы типа, которые делают вас конструктором типов. Каждый из Either и () является конструктором, но применение Either к () не является, потому что это не одно имя уровня типа, созданное объявлением data или newtype. Точно так же, m является переменной типа, а не конструктором - ее значение не фиксируется ни одним объявлением data или newtype.

Помимо конструкторов и переменных, в стандартном Haskell есть еще один тип имени уровня типа: псевдонимы типов. Существует два основных различия между псевдонимами типов и конструкторами:

  1. Конструкторы являются инъективными, псевдонимы могут не быть. Если FooC a b c и FooC a' b' c' имеют одинаковый тип, а FooC является конструктором, тогда a и a' имеют одинаковый тип, b и b' имеют одинаковый тип, а c и c' того же типа. Контраст

    type FooA a = String
    

    , в котором FooA () и FooA Bool относятся к одному типу, хотя () и Bool не относятся к одному типу.

  2. Конструкторы могут быть применены частично, псевдонимы типов не могут быть. Например, если вы напишите

    type BarA a = Maybe a
    

    тогда StateT Int BarA () недопустимо - BarA всегда должен быть немедленно передан аргумент типа - даже если StateT Int Maybe () имеет значение. Конечно, с

    type BarEtaA = Maybe
    

    затем StateT Int BarEtaA () снова допустим, потому что псевдоним BarEtaA не нуждается в аргументах, прежде чем он расширится до определенного значения Maybe.

Есть некоторые другие небольшие различия между псевдонимами и конструкторами, но они не являются фундаментальными (и смягчаются подходящими расширениями GHC).

Существует только одно различие между конструкторами и переменными, о котором я могу подумать в стандартном Haskell, а именно их взаимодействие с механизмом классов типов. В частности, экземпляры должны иметь форму instance <class> (<constructor> <variable> <variable> <variable> ...) where ..., а ограничения / контексты должны иметь форму <class> (<constructor> <variable> <variable> ...) => .... Эти ограничения ослаблены подходящими расширениями GHC.

Extended Haskell, реализованный GHC, также включает в себя две другие формы определенных имен на уровне типов, семейства типов и семейства данных, которые смешивают некоторые из перечисленных выше свойств. Имена, определяемые семействами данных, очень похожи на конструкторы (они инъективны и могут применяться частично), в то время как имена, определяемые семействами типов, очень похожи на псевдонимы (они не гарантированно являются инъективными и не могут применяться частично). Основное отличие состоит в том, что они могут выполнять «сопоставление с образцом на уровне типа», в котором есть несколько определений, которые применяются в разных случаях. Полное описание, вероятно, не вписывается в ответ StackOverflow, но руководство описывает их и ссылки на несколько длинных статей, обсуждающих их.

...