Типы сумм - почему в Haskell `show (Int | Double)` отличается от `(show Int) | (показать дубль) `

9

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

show $ if someCondition then someInt else some double

а также

if someCondition then show someInt else show someDouble

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

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

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

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

Мехди Саффар
источник
2
An if ... then ... else ..., должен иметь тот же тип в thenи elseчасти. Вы можете видеть это как троичный оператор в некоторых языках программирования.
Виллем Ван Онсем
1
Я согласен с making all conversions explicit. В моем вопросе я не хочу, чтобы Haskell использовал Inta Doubleили наоборот. Я просто использовал эти два типа в качестве примера. Вы могли бы заменить каждый Intс aи Doubleс bв моем вопросе , где оба типа наследуют Show. Я понимаю, что anonymous sum typesв Haskell их нет, но я хотел бы знать, почему это так и что мешает нам разработать язык для его использования.
Мехди Саффар
4
Я думаю, что такие типы называются типами объединения . Тип суммы по сути является теговым вариантом типа объединения, где каждое значение должно содержать левую / правую метку за пределами значения внутреннего типа. Я ожидаю, что вывод типов с объединением типов со всеми функциями уровня типов в Haskell будет очень труднодостижимым. Если x :: Int | Boolи нам нужно скомпилировать show x, нет простого способа узнать, какой указатель на функцию использовать для вызова show, в RTS на основе стирания типа. Мы, вероятно, должны были бы хранить некоторую информацию уровня типа во время выполнения.
Чи
1
Отсутствие анонимных типов сумм - это дизайнерское решение дизайнеров Haskell. Я не совсем уверен, какую пользу они принесут на стол, но я вижу, где они могут усложнить ситуацию. Поэтому я предполагаю, что они не учтены, потому что соотношение затрат и выгод отсутствует. Но чтобы быть абсолютно уверенным, вам нужно спросить оригинального языка дизайнеров и / или текущих сопровождающих. Я не думаю, что это сделало бы большой вопрос SO, потому что в разработке языка очень много личных мнений и вкусов.
нет. местоимения м.
4
(String, Int)не является анонимным Это обычный продукт с забавным синтаксисом. (String | Int)было бы совсем по-другому. Начните с вопроса о том, (Int|Int)должен ли он быть идентичным Intи почему.
нет. местоимения м.

Ответы:

8

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

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

Джозеф Сибл-Восстановить Монику
источник
Не могли бы вы уточнить разницу между типами объединения / пересечения и типами суммы / продукта? Я всегда думал, что они были одинаковыми, кроме анонимности?
Мехди Саффар
1
@MehdiSaffar Anonymous, как в нетегированной, а не в неназванном конструкторе. Другими словами, если у вас есть Int ∪ Double, то вы бы знали, что у вас есть один из двух, но не смогли бы сопоставить с шаблоном, чтобы увидеть, какой, поэтому вы могли бы делать только то, что было бы допустимо для обеих возможностей.
Джозеф Сибл-Восстановить Монику
2
Для ясности, TypeScript имеет информацию о типе, доступную во время выполнения, поэтому у него есть typeofоператор, который может восполнить отсутствие тегов и посмотреть, какой тип используется в любом случае. Haskell полностью стерт, поэтому если он поддерживает эту функцию, то не будет никакого эквивалента этому.
Джозеф Сибл-Восстановить Монику
7

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

if someCondition then 42 else "helloWorld"

Если это должно вернуть значение типа like (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, вы знаете, где его найти.

п. местоимения м.
источник
1
@MichaWiedenmann Честно говоря, я не знаю, правильное ли слово "релевантно". Я думаю, что это так или иначе полезно. Да, я остановился на мгновение и подумал, стоит ли включать это. Но иногда я ошибаюсь.
нет. местоимения м.
Нет проблем, это ваш пост, вы решаете.
Миха Виденманн
Так какие у тебя местоимения?
Dfeuer