Подтвердить что ты не робот

Что такое [] (конструктор списков) в Haskell?

У меня возникают проблемы с пониманием функторов, в частности, конкретного типа в LYAH. Я считаю, что это потому, что я не понимаю, что такое [].

fmap :: (a -> b) -> f a -> f b  
  • Является [], конструктором типа? Или это конструктор значений?
  • Что значит иметь тип: [] :: [a]?
  • Это как конструктор типа Maybe или конструктор значений Just?
    • Если это похоже на Just, то как получилось, что Just имеет подпись типа Just :: a -> Maybe a, а не Just :: Maybe a, иными словами, почему не [] typed [] :: a -> [a]
  • LYAH говорит об этом, поскольку он применим к функторам: Обратите внимание, что мы не пишем экземпляр Functor [a] где, потому что из fmap:: (a → b) → fa → fb, мы видим, что f должен быть конструктором типа, который принимает один тип. [a] уже является конкретным типом (из списка с любым типом внутри него), а [] - это конструктор типа, который принимает один тип и может создавать такие типы, как [Int], [String] или даже [[String] ]. Я смущен, хотя тип [] означает, что он похож на литерал для [a], к чему стремится LYAH?
4b9b3361

Ответ 1

Тип описан (в сеансе GHCI) как:

$ ghci
Prelude> :info []
data [] a = [] | a : [a] -- Defined 

Мы также можем думать об этом, как если бы он был определен как:

data List a = Nil
            | Cons a (List a)

или

data List a = EmptyList
            | ListElement a (List a)

Конструктор типов

[a] - это тип полиморфных данных, который также можно записать [] a, как указано выше. Об этом можно подумать, как будто это было List a

В этом случае [] является конструктором типа, принимающим один аргумент типа a и возвращающим тип [] a, который также разрешен для записи как [a].

Можно написать тип функции, например:

sum :: (Num a) => [a] -> a

Конструктор данных

[] - это конструктор данных, который по существу означает "пустой список". Этот конструктор данных не принимает аргументов значения.

Существует еще один конструктор данных :, который добавляет элемент в начало другого списка. Подпись для этого конструктора данных a : [a] - он принимает элемент и другой список элементов и возвращает результирующий список элементов.

Обозначение [] также может использоваться в качестве сокращения для построения списка. Обычно мы строили бы список как:

myNums = 3 : 2 : 4 : 7 : 12 : 8 : []

который интерпретируется как

myNums = 3 : (2 : (4 : (7 : (12 : (8 : [])))))

но Haskell разрешает нам также использовать сокращенное

myNums = [ 3, 2, 4, 7, 12, 8 ]

как эквивалентный по смыслу, но немного приятный внешний вид, обозначение.

Неоднозначный случай

Существует неоднозначный случай, который обычно встречается: [a]. В зависимости от контекста это обозначение может означать либо "список a 's", либо "список с одним элементом, а именно a". Первое значение - это предполагаемое значение, когда [a] появляется внутри типа, тогда как второе значение является предполагаемым значением, когда [a] появляется внутри значения.

Ответ 2

  • Это (путающе, я вам даю) синтаксически перегружено, чтобы быть как конструктором типа, так и конструктором значений.

  • Это означает, что (конструктор значений) [] имеет тип, который для всех типов a является списком a (который записывается [a]). Это связано с тем, что в каждом типе есть пустой список.

  • Конструктор значений [] не набирается a -> [a], потому что в пустом списке нет элементов, и поэтому ему не нужно a, чтобы создать пустой список a. Сравните вместо Nothing :: Maybe a.

  • LYAH говорит о конструкторе типа [] с видом * -> *, в отличие от конструктора значений [] с типом [a].

Ответ 3

  • это конструктор типа (например, [Int] - это тип), а конструктор данных ([2] - структура списка).
  • Пустым списком является список, содержащий любой тип
  • [a] подобен, возможно, a, [2] похож на Just 2.
  • [] - это нулевая функция (константа), поэтому она не имеет типа функции.

Ответ 4

Чтобы сделать вещи более явными, этот тип данных:

data List a = Cons a (List a) 
            | Nil

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

  • List= [], введите конструкторы с видом * -> *
  • List a= [a], типы с видом *
  • Nil= [], значения с полиморфными типами List a и [a] соответственно
  • Cons= :, конструкторы данных с типами a -> List a -> List a и a -> [a] -> [a] соответственно
  • Cons 5 Nil= [5] или 5:[], списки отдельных элементов
  • f Nil = ...= f [] = ..., сопоставление пустых списков шаблонов
  • f (Cons x Nil) = ...= f [x] =... `, сопоставление одноуровневых списков с образцами
  • f (Cons x xs) = ...= f (x:xs) = ..., соответствие шаблону непустым спискам

В самом деле, если вы спросите ghci о [], он говорит вам почти то же определение:

> :i []
data [] a = [] | a : [a]           -- Defined in GHC.Types

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