Введіть умовивід у Golang / Haskell


9

Я читав, що Go насправді не має істинного висновку про тип у тому сенсі, як функціональні мови, такі як ML або Haskell, але мені не вдалося знайти просте для розуміння порівняння двох версій. Чи може хтось пояснити в основних термінах, як висновок типу в Go відрізняється від виводу типу в Haskell і від плюсів / мінусів кожного?

Відповіді:


13

Дивіться цю відповідь StackOverflow щодо виводу типу Go. Я сам не знайомий з Go, але виходячи з цієї відповіді, це здається односторонньою «типовою дедукцією» (запозичити деяку темологію C ++). Це означає, що якщо у вас є:

x := y + z

тоді тип xвиводиться, з'ясовуючи тип y + z, що для компілятора порівняно тривіально. Для цього типи yта zпотрібно знати апріорно : це можна зробити за допомогою анотацій типів або зробити висновок із призначених їм літералів.


Навпаки, більшість функціональних мов мають умовивід типу, який використовує всю можливу інформацію в межах модуля (або функції, якщо алгоритм виводу є локальним) для отримання типу змінних. Складні алгоритми висновків (наприклад, Хіндлі-Мілнер) часто включають певну форму об'єднання типів (трохи схожу на розв’язання рівнянь) за лаштунками. Наприклад, у Haskell, якщо ви пишете:

let x = y + z

то Haskell може вивести тип не тільки , xале також yі zпросто на підставі того , що ви виконуєте додавання на них. В цьому випадку:

x :: Num a => a
y :: Num a => a
z :: Num a => a

(Нижній регістр aтут позначає поліморфний тип , який часто називають "generics" іншими мовами, такими як C ++. Num a =>Частина є обмеженням, що вказує на те, що aпідтримка типу має певне поняття додавання.)

Ось більш цікавий приклад: комбінатор з фіксованою точкою, який дозволяє визначити будь-яку рекурсивну функцію:

let fix f = f (fix f)

Зауважте, що ніде ми не вказали тип f, а також не вказали тип fix, але компілятор Haskell може автоматично визначити, що:

f :: t -> t
fix :: (t -> t) -> t

Це говорить про те, що:

  • Параметр fповинен бути функцією від якогось довільного типу tдо одного типу t.
  • fixце функція, яка отримує параметр типу t -> tі повертає результат типу t.

4
більш точно, Haskell можна сказати , що x, y, zтака ж Numтип Еріка, але вони все ще можуть бути Integers, DoubleS, Ratio IntegerS ... Haskell готовий зробити довільний вибір між числовими типами, але не для інших класів типів.
Джон Дворак

7

Вибір типу в Go дуже обмежений і надзвичайно простий. Він працює лише в одній мовній конструкції (змінної декларації) і просто приймає тип правої частини і використовує її як тип для змінної з лівого боку.

Вибір типу в Haskell може використовуватися скрізь, він може використовуватися для виведення типів для всієї програми. Він заснований на об'єднанні, що означає, що (концептуально) всі типи виводяться "відразу" і всі вони можуть впливати один на одного: у Go, інформація про тип може надходити лише з правого боку змінної декларації вліво- сторона, ніколи в інший бік і ніколи поза змінною декларацією; в Хаскеллі введіть інформацію вільно в усі сторони через всю програму.

Однак система типів Haskell настільки потужна, що умовивід типу фактично не може зробити висновок про тип (а точніше: потрібно встановити обмеження, щоб завжди можна було зробити висновок про тип). Система типу Go настільки проста (ні підтипу, ні параметричного поліморфізму), а її висновок настільки обмежений, що завжди вдається.


4
"В Haskell вводити інформацію вільно в усі сторони через всю програму": я вважаю, що це дає дуже гарну інтуїцію. +1
Джорджіо

Твердження, які ця відповідь висловлює в останньому абзаці, є дещо оманливими. У Haskell немає підтипу. Крім того, параметричний поліморфізм не викликає жодних проблем для повноти виводу типу: Хіндлі-Мілнер на поліморфному обчисленні лямбда завжди знаходить найбільш загальний тип. Haskell не може зробити висновок про типи, але це стосуватиметься складних системних функцій типу GADT, де при наївному формулюванні не існує принципового (тобто "кращого вибору") типу.
Едвард З. Ян
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.