Подтвердите или исправьте мою “английскую интерпретацию” этого фрагмента кода Haskell

Если вы используете Spring Framework Check, вы применили @transactional. В противном случае вы сообщите полное описание, какую платформу вы используете. Просто проверьте правильность вашей конфигурации?

13
задан Will Ness 17 August 2018 в 18:44
поделиться

8 ответов

  • Конструктор значения "Cons" имеет параметр одного типа.

Нет: вы уже параметризовали его, когда объявили список данных a . Одним из эффективных свойств этого является то, что если у меня есть Nil :: List Int, я не могу поменять его на Nil :: List Char.

  • Если вы используете конструктор значений «Cons», то есть 2 поля, которые должны предоставляться. Первое обязательное поле - это экземпляр List. Второе обязательное поле - это экземпляр a.

Вы поменялись местами: первое обязательное поле - это экземпляр a, второе поле - это экземпляр List.

Эта глава из Real World Haskell может представлять интерес.

Спасибо. Это глава, в которой я сейчас нахожусь. Итак ... когда в коде написано "Минусы а (список а)", я подумал "Минусы а" частично это указывало на то, что конструктор значения Cons был параметризован. Они еще не охватили синтаксис для параметризованных типов, поэтому я догадался, что синтаксис должен требовать повторного указания «a», если вы собираетесь использовать a. Но вы говорите, что это не нужно? И поэтому это не то, что означает «а»?

Нет. После того, как мы объявили параметр в нашем типе, мы можем использовать его повторно, чтобы сказать «этот тип должен использоваться там». Это немного похоже на сигнатуру типа a -> b -> a : a параметризует тип, но тогда я должен использовать то же самое, что и возвращаемое значение.

ОК, но это запутанный. Кажется, что первое «a» означает «первое поле является экземпляром a»,

Нет, то есть не верно. Это просто означает, что тип данных параметризуется по некоторому типу a.

, и это также означает, что «первое поле имеет то же значение, что и значение, которое они передали для a». Другими словами, он указывает значение типа AND.

Нет, это также не соответствует действительности.

Вот поучительный пример, синтаксис которого вы могли видеть или не видеть раньше:

foo :: Num a => a -> a

Это довольно стандартный подпись для функции, которая принимает число, что-то с ним делает и дает вам другой номер. Что я на самом деле подразумеваю под «числом» в языке Haskell, тем не менее, это некоторый произвольный тип «a», который реализует класс «Num».

Таким образом, это анализируется на английском языке:

Позвольте a указать тип реализуя класс типов Num, тогда сигнатура этого метода - один параметр с типом a, и возвращаемое значение типа a

Нечто подобное происходит с данными.

Мне также приходит в голову, что экземпляр List в спецификации Cons также сбивает вас с толку: будьте очень осторожны при разборе этого: тогда как Cons является указание конструктора, который по сути является шаблоном, в который Haskell собирается обернуть данные, (List a) выглядит как конструктор, но на самом деле это просто тип, такой как Int или Double. a - это тип, а не значение в каком-либо смысле этого термина.

Редактировать: В ответ на самое последнее редактирование.

Я думаю, что сначала требуется анализ. Затем я буду разбираться с вашими вопросами по пунктам.

Конструкторы данных на Haskell немного странные, потому что вы определяете сигнатуру конструктора, и вам не нужно создавать никаких других скаффолдингов. Типы данных в Haskell не имеют представления о переменной-члене. (Заметка: есть альтернативный синтаксис, к которому такой способ мышления более удобен, но давайте пока проигнорируем его).

Другое дело, что код на Haskell является плотным; его тип подписи таковы. Поэтому ожидайте увидеть один и тот же символ, повторно используемый в разных контекстах. Вывод типа также играет здесь большую роль.

Итак, вернемся к вашему типу:

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

Я разбил его на несколько частей:

data List a

Это определяет имя типа и любые параметризованные типы, которые будут у него позже. , Обратите внимание, что вы увидите это только в сигнатурах других типов.

Cons a (List a) |
Nil

Это имя конструктора данных. Это НЕ тип . Однако мы можем сопоставить его с шаблоном, ala:

foo :: List a -> Bool
foo Nil = True

Обратите внимание, как List a является типом в сигнатуре, а Nil является и конструктором данных, и «вещью», для которой мы сопоставляем шаблон.

Cons a (List a)

Это типы значений, которые мы вставляем в конструктор. Минусы имеют две записи, одна имеет тип a, а другая имеет тип List a.

Итак, мой вопрос: почему «a» в первом поле означает «тип этого поля -« a », а значение этого поля есть «a» », в то время как« a »во втором поле означает только« тип этого поля - «Список a» »?

Простой: не думайте, что мы указываем тип; думаю, что Haskell выводит тип из этого. Таким образом, для наших намерений и целей мы просто вставляем туда 0, а во втором разделе ноль. Затем Хаскелл смотрит на наш код и думает:

  • Хмм, мне интересно, какой тип Cons 0 Nil
  • Ну, Cons является конструктором данных для List a. Интересно, что это за тип List a?
  • Ну,
8
ответ дан 1 December 2019 в 21:53
поделиться

Возможно, вам придется использовать вместо этого метод RowNumber ().

Вот пример:

DECLARE @PageNum AS INT;
DECLARE @PageSize AS INT;
SET @PageNum = 2;
SET @PageSize = 10;

WITH OrdersRN AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY OrderDate, OrderID) AS RowNum
          ,OrderID
          ,OrderDate
          ,CustomerID
          ,EmployeeID
      FROM dbo.Orders
)

SELECT * 
  FROM OrdersRN
 WHERE RowNum BETWEEN (@PageNum - 1) * @PageSize + 1 
                  AND @PageNum * @PageSize
 ORDER BY OrderDate
         ,OrderID;

РЕДАКТИРОВАТЬ Или вы можете использовать скобки ... которые Я не знал об этом в то время :) Спасибо, ребята.

Там, где аналогия не удалась.

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

(И, пожалуйста, прокомментируйте, как это ужасное сравнение не оправдывает типы данных Haskell.)

4
ответ дан 1 December 2019 в 21:53
поделиться
Cons a (List a)

Первое поле Cons является значением типа " a ". Вторым является значение типа « List a », т.е. список, параметризованный с тем же типом, что и параметр текущего списка.

3
ответ дан 1 December 2019 в 21:53
поделиться

5 неверно, и я бы сказал 6, чтобы заменить оба:

Cons {1} a {2} (Список a) {3} - это конструктор с именем Cons ( часть перед {1}) для значения типа List a (данные List часть), для которого требуется два значения: одно из типа a (часть между {1} ​​и {2}) и одно из типа List a (часть между {2} и {3}).

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

3
ответ дан 1 December 2019 в 21:53
поделиться

When I type "Cons 0 Nil", it uses the "Cons" value constructor to create an instance of List. From 0, it learns that the type parameter is "Integer". So far, no confusion.

However, it also determines that the value of the first field of the Cons is 0. Yet it determines nothing about the value of the second field ... it only determines that the second field has a type of "List Integer".

No, it determines that the second field's value is Nil. Given your definition, Nil is a value of the type List a. Therefore so is Cons 0 Nil. And in Cons 1 it the second field's value is it; i.e., Cons 0 Nil. This is precisely what the REPL shows: Cons 1 (Cons 0 Nil).

2
ответ дан 1 December 2019 в 21:53
поделиться

Да, синтаксис данных немного сбивает с толку, потому что он пробивает имена и типы и на самом деле не делает синтаксическое различие между ними. В частности, в определении конструктора, например:

Cons a (List a)

Первое слово - это имя конструктора; любое другое слово - это имя некоторого предварительно объявленного типа. Таким образом, a и List a уже находятся в области действия ( a были включены в область действия a in » перечислите данные "), и вы говорите, что это типы параметров. Их роль лучше продемонстрировать, указав то же самое, используя синтаксис записи :

Cons { headL :: a, tailL :: List a }

Т.е. значение типа List Int , , если было создано с Минусы конструктор, имеет два поля: Int и List Int . Если он был построен с ноль , он не имеет полей.

3
ответ дан 1 December 2019 в 21:53
поделиться

Я посмотрел на ваш отредактированный вопрос.

Когда я создаю экземпляры, используя Cons конструктор значения, эти экземпляры «интерпретировать» первое «а» как значение «поместите здесь значение, переданное здесь.

В« Минусах a (Список а) »и« a », и« Список a »являются типами. Я не понимаю, какое значение имеет« значение ».

Когда я набираю «Минусы 0 ноль», он использует Значение конструктора "Минусы" для создания экземпляр списка. С 0 он учится что тип параметра "Целое число". Пока что нет путаницы.

Однако, это также определяет, что Значение первого поля минусов равно 0. Но это ничего не определяет о значение второго поля ... это только определяет, что второе поле имеет тип «Список целых чисел».

Значение второго поля равно Ноль .

Так что мой вопрос, почему «а» в первое поле означает "тип этого поле «а» и значение этого поле «а», а «а» во втором поле означает только «тип этого поле «Список a» »?

« a »в первом поле означает« тип этого поля - «a» ».« Список a »во втором поле означает« тип этого поля - «Список» a '". В случае" Cons 0 Nil "выше," a "подразумевается как" Integer ". Таким образом," Cons a (List a) "становится" Cons Integer (List Integer) ". 0 является значением типа Integer. Nil - это значение типа «List Integer».

значение этого поля равно «a»

Я не понимаю, что вы подразумеваете под этим. «a» является переменной типа; какое это имеет отношение к ценностям?

1
ответ дан 1 December 2019 в 21:53
поделиться

Просто чтобы дать вам дополнительную "помощь", если вы все еще смотрите эту ветку. В Haskell есть несколько соглашений, которые портят представления других о том, как что-то должно быть сделано - в Haskell параметризованный тип настолько широко распространен, что его обычно считают функцией уровня типа. Точно так же конструкторы значений считаются «специальными» функциями, которые также позволяют сопоставление с образцом в дополнение к их «получению значения (или более) и выдаче значения в результате».

Еще одна «забавная» характеристика Haskell заключается в том, что он не вычисляет явно (или неявно) аргументы функции , даже если этот аргумент заключен в круглые скобки . Позвольте мне заявить об этом несколько иначе: функции Haskell не оценивают аргументы в круглых скобках перед другими аргументами. Аргументы заключаются в круглые скобки только для группировки, а не для того, чтобы они оценивались «первыми». Haskell назначает аргументы функции («применяет») с более высоким приоритетом, чем любая другая операция - даже выше, чем неявное применение функции одного из своих собственных аргументов.Вот почему конструктор Cons имеет скобки вокруг второго аргумента, (List a) - чтобы сообщить компилятору, что Cons имеет два аргумента, а не ] три . Скобки предназначены только для группировки, а не для приоритета!

Будьте осторожны с типами в F # в качестве побочной темы. Поскольку F # имеет свои корни в ML, его параметризованные типы имеют параметры впереди - int list , а не ( List Int ) сзади! Haskell делает это по-другому, потому что так же, как Haskell выполняет функции - сначала функция, затем аргументы функции. Это поощряет общий шаблон использования и объясняет, почему типы и конструкторы значений Haskell пишутся с заглавной буквы - чтобы напомнить вам, что вы имеете дело с вещами, связанными с типом / классом.

Хорошо, я закончил; спасибо, что позволили мне повесить этот огромный текст Wall O 'на вашем участке ...

0
ответ дан 1 December 2019 в 21:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: