Типы сумм - почему в Haskell `show (Int | Double)` отличается от `(show Int) |(показать дубль) ` - PullRequest
8 голосов
/ 09 ноября 2019

Почему они не эквивалентны?

show $ if someCondition then someInt else some double

и

if someCondition then show someInt else show someDouble

Я понимаю, что если вы выделите часть if ... else в первом примере для выражения, то выне может представлять его тип с помощью анонимного типа суммы, типа Int | Double, как то, что вы могли бы легко сделать в TypeScript (упоминая TypeScript, потому что это язык, который я часто использовал и который поддерживает типы Sum), и должен был бы прибегнуть киспользование данных Either, основанных на них, вызовет show.

Пример, который я привел здесь, тривиален, но для меня имеет больше смысла думать: «Хорошо, мы собираемся показать что-то, и эточто-то зависит от someCondition ", а не" Хорошо, если someCondition имеет значение true, тогда show someInt иначе покажет someDouble ", а также допускает меньшее дублирование кода (здесь показ повторяется дважды, но это также может быть приложение с длинной функцией и вместоif ... else может быть> 2 ветки для рассмотрения)

На мой взгляд, компилятору должно быть легко проверить, каждый лииз типов, которые составляют тип суммы (здесь Int | Double), может использоваться в качестве параметра функции show и решает, являются ли типы правильными или нет. Еще лучше то, что функция show всегда возвращает string независимо от типов параметров, поэтому компилятору не нужно переносить с собой все возможные «ветви» (то есть все возможные типы).

Это по выбору, что такая функция не существует? Или я думаю, что это сложнее?

Ответы [ 2 ]

8 голосов
/ 09 ноября 2019

Все части выражения должны быть хорошо напечатаны. Тип if someCondition then someInt else someDouble должен быть примерно таким же, как exists a. Show a => a, но Haskell не поддерживает такого рода экзистенциальное количественное определение.

Обновление: как указывает chi в комментарии ,это также было бы возможно, если бы Haskell имел поддержку типов объединения / пересечения (которые не совпадают с типами sum / product), но, к сожалению, этого не происходит.

6 голосов
/ 09 ноября 2019

В Haskell есть типы продуктов с облегченным синтаксисом, написанные (,). Можно было бы подумать, что тип суммы с легким синтаксисом, например, (Int | String), был бы отличной идеей. Реальность сложнее. Давайте посмотрим почему (я беру некоторые вольности с Num, они не важны).

if someCondition then 42 else "helloWorld"

Если при этом должно возвращаться значение типа типа (Int | String), то что должно возвращать следующее значение?

if someCondition then 42 else 0

(Int | Int), очевидно, но если это отличается от простогоInt тогда у нас большие проблемы. Таким образом, (Int | Int) должен быть идентичен обычному Int.

. Сразу видно, что это не просто упрощенный синтаксис для типов сумм, а совершенно новая языковая функция. Другой тип системы типов, если хотите. Должен ли он быть у нас?

Давайте посмотрим на эту функцию.

mysteryType x a b = if x then a else b

Теперь, какой тип имеет mysteryType? Очевидно

mysteryType :: Bool -> a -> b -> (a|b)

верно? А что если a и b одного типа?

let x = mysteryType True 42 0

Это должно быть просто Int, как мы договорились ранее. Теперь mysteryType иногда возвращает тип анонимной суммы, а иногда нет, в зависимости от того, какие аргументы вы передаете. Как бы вы сопоставили шаблон с таким выражением? Что на земле вы можете сделать с этим? За исключением тривиальных вещей, таких как «show» (или любых других методов классов типов, которые он будет использовать), не так уж много. Если только вы не добавите информацию о типе времени выполнения к языку, то есть typeof будет доступен - и это сделает Haskell совершенно другим языком.

Так что да. Почему Haskell не является TypeScript? Потому что нам не нужен другой TypeScript. Если вам нужен TypeScript, вы знаете, где его найти.

...