Типи сум - Чому в Haskell `show (Int | Double)` відрізняється від `(показати Int) | (показати подвійний) `


9

Чому вони не є рівнозначними?

show $ if someCondition then someInt else some double

і

if someCondition then show someInt else show someDouble

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

Приклад, який я наводив тут, є тривіальним, але для мене є більше сенсу думати "Гаразд, ми збираємось щось показати, і від цього щось залежить someCondition", а не "Добре, якщо деяка умова справжня, то покажіть інше, якщо в іншому випадку покажіть дещо подвійне", а також дозволяє для меншого дублювання коду (тут показ повторюється двічі, але це також може бути додатково функціональне додаток, а замість 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. Я не зовсім впевнений, яку користь вони принесуть до столу, я трохи не бачу, де вони ускладнять речі. Тому я здогадуюсь, що вони залишилися поза межами, оскільки співвідношення витрат і вигод не існує. Але, щоб бути абсолютно впевненим, вам потрібно запитати дизайнерів оригінальної мови та / або поточних обслуговуючих служб. Я не думаю, що це викликало б велике питання, оскільки існує велика кількість особистих думок та смаків, що стосуються дизайну мови.
н. 'займенники' м.

4
(String, Int)не є анонімним. Це просто звичайний тип продукту із кумедним синтаксисом. (String | Int)було б зовсім іншим. Почніть з того, щоб запитати себе, чи (Int|Int)слід ідентично Intі чому.
н. 'займенники' м.

Відповіді:


8

Усі частини виразу повинні бути добре набрані. Тип цього if someCondition then someInt else someDoubleповинен був бути чимось подібним exists a. Show a => a, але Haskell не підтримує такого роду екзистенціальне кількісне визначення.

Оновлення: Як чі вказує в коментарі , це також було б можливим, якби у Haskell була підтримка типів об'єднання / перетину (які не збігаються з типом суми / продукту), але це, на жаль, не відбувається.


Чи можете ви, будь ласка, детальніше розібратися в різниці між типами з'єднання / перетину та типами сум / продуктів? Я завжди думав, що вони однакові, за винятком анонімності?
Мехді Саффар

1
@MehdiSaffar Anonymous як у безтепному, а не як у неназваному конструкторі. Іншими словами, якщо у вас є Int ∪ Double, то ви б знали, що у вас є одне з двох, але ви не зможете вирівняти відповідність, щоб побачити це, тож ви могли робити лише те, що було б дійсно для обох можливостей.
Джозеф Сибл-

2
Для наочності TypeScript має інформацію про тип, доступну під час виконання, тому він має typeofоператора, який може компенсувати відсутність тегів і побачити, який тип використовується в будь-якому випадку. Haskell повністю стирається, тому якби він підтримував цю функцію, то не було б подібного до цього.
Джозеф Сибл-

7

Існують типи продуктів із полегшеним синтаксисом, написані (,)на 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, ви знаєте, де його знайти.


1
@MichaWiedenmann Чесно кажучи, я не знаю, чи "відповідне" - це правильне слово. Я думаю, що це корисно так чи інакше. Так, я на мить зупинився і подумав, чи включити його. Але мені відомо, що часом помиляюся.
н. 'займенники' м.

Без проблем, це ваша посада, ви вирішите.
Micha Wiedenmann

То які ваші займенники?
dfeuer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.