Функція ML типу 'a ->' b


19

Наш професор попросив нас придумати функцію в OCaml, яка має такий тип

'a -> 'b

тобто функція одного аргументу, який може бути будь-яким, і який може повернути інше що завгодно.

Я думав використовувати raiseу функції, яка ігнорує її аргумент:

let f x = raise Exit

Але професор сказав, що в стандартній бібліотеці є рішення, яке не вимагає жодної функції. Я розгублений: як ви можете зробити це, 'bякщо у вас його немає в першу чергу?

Я прошу тут, а не Stack Overflow, тому що я хочу зрозуміти, що відбувається, я не хочу просто бачити програму без пояснень.


2
Будь ласка, націліть на свою відповідь програмування учня CS101, а не теоретик типу, на який ваша відповідь може надихнути його згодом стати.
Жил 'ТАК - перестань бути злим'

Це допоможе, якби ви пояснили, як ви зрозуміли, що raiseце спрацює, тому ми знаємо, як найкраще пояснити, чому саме шукає рішення, яке шукає ваш проф raise.
sepp2k

@ sepp2k, raise : exn -> 'aщоб я міг отримати повернене значення, я просто ігнорую аргумент.
Жил "ТАК - перестань бути злим"


Відповіді:


18

Скелет є let f x = BODY. У BODY ви повинні використовувати x лише загальними способами (наприклад, не надсилайте його до функції, яка очікує цілих чисел), і ви повинні повернути значення будь-якого іншого типу. Але як остання частина може бути правдивою? Єдиний спосіб задовольнити вислів "для всіх типів 'bповернене значення - це значення типу 'b" - це переконатися, що функція не повертається. Існує рівно дві можливості: або BODY несправності, або вона не припиняється. Функція raiseпомилок, наступне не припиняється:

let rec f x = f x

19

По-перше, кілька зауважень. Використовуючи лише основне лямбда-числення, набране ядром, це неможливо отримати, 'a -> 'bоскільки система набору тексту відповідає (через ізоморфізм Керрі Говарда ) інтуїтивістській логіці, а відповідна формула A → Bне є тавтологією.

Інші розширення , такі як кортежі і паросполучення / умовні все ще зберігають деякі логіки консистенції додають видів продукції , *які відповідають логічної зв'язці і та типи сум , |які відповідають або . Знову ж таки, не чекайте, що вони випускають цей 'a -> 'bтип, оскільки це дозволить довести певну формулу, яка не є тавтологією.

Тож ваші єдині шанси - це використання інших конструкцій, які виходять із логіки на кшталт raise(але в цьому випадку вам не дозволено)… або let rec! Рекурсія дозволяє будувати програми, які ніколи не припиняються, і їх результатам можна надати довільний тип повернення, оскільки вони ніколи не будуть вироблятися. Тепер якщо ви думаєте про найтривіальнішу функцію, що не закінчується (ту, яка безпосередньо закликає себе повернути результат):

let rec f x = f x

Ви помітите, що його тип точно такий 'a -> 'b: як би не був аргументований аргумент, результат (який ніколи не буде обчислюватися) може вважати, що він має будь-який тип.

Звичайно, це fне цікава функція, але в цьому справа. У OCaml будь-яка функція, тип якої не схожа на дійсну формулу, є підозрілою функцією.


Запитувач не зрозумів ні слова ваших перших двох абзаців, але мені подобається ваше речення: "їх результатам можна надати довільний тип повернення, оскільки вони ніколи не будуть видані".
Жил "ТАК - перестань бути злим"

1

За допомогою примітиву компілятора ви можете написати це:

external magic: 'a -> 'b = "%identity"

(і насправді розподіл компілятора надає це, хоча не є частиною мови). Це небезпечний акторський склад.

Ваш професор майже точно не хоче цього. Однак це також єдина корисна функція з типом, про 'a -> 'bяку я знаю, і вона справді використовується в самому розповсюдженні OCaml.

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