Як заголовок: як є гарантія оцінювання блоку повернення функції Haskell? Можна подумати, що немає необхідності проводити будь-яку оцінку в такому випадку, компілятор міг би замінити всі такі виклики на негайне ()значення, якщо немає явних запитів на суворість, і в цьому випадку код може вирішити, чи слід повернення ()або дно.
Я експериментував з цим у GHCi, і, схоже, відбувається навпаки, тобто така функція, схоже, оцінюється. Дуже примітивний приклад був би
f :: a -> ()
f _ = undefined
Оцінювання f 1кидає помилку через наявність undefined, тому певна оцінка точно відбувається. Не ясно, наскільки глибоко йде оцінка; іноді, схоже, йдеться настільки глибоко, як це необхідно для оцінки всіх дзвінків до функцій, що повертаються (). Приклад:
g :: [a] -> ()
g [] = ()
g (_:xs) = g xs
Цей код замикається на невизначений термін, якщо він представлений g (let x = 1:x in x). Але потім
f :: a -> ()
f _ = undefined
h :: a -> ()
h _ = ()
може бути використаний для показу, що h (f 1)повертається (), тому в цьому випадку оцінюються не всі одиничні вираження під вираженнями. Яке тут загальне правило?
ЕТА: звичайно, я знаю про лінь. Я запитую, що заважає авторам-компіляторам зробити цей конкретний випадок ще лінивішим, ніж це можливо.
ETA2: підсумок прикладів: GHC, як видається, трактує ()точно так само, як і будь-який інший тип, тобто як би виникає питання про те, яке регулярне значення, що населяє тип, має бути повернуто з функції. Те, що існує лише одне таке значення, схоже, не використовується (ab), що використовується алгоритмами оптимізації.
ETA3: коли я кажу Haskell, я маю на увазі Haskell як визначено у звіті, а не Haskell-H-in-GHC. Здається, це припущення, яке не поділяється так широко, як я уявляв (це було «на 100% читачів»), або я, певно, міг би сформулювати більш чітке питання. Незважаючи на це, я шкодую, що змінив назву питання, оскільки спочатку запитував, які існують гарантії для такої функції.
ETA4: Здавалося б, це питання пробігло свій шлях, і я вважаю його без відповіді. (Я шукав функцію "закритого запитання", але знайшов лише "відповідь на власне запитання", і оскільки на нього не можна відповісти, я не пішов по цьому маршруту.) Зі Звіту ніхто не підніс нічого, що вирішило б це так чи інакше , яку я спокусив трактувати як категоричну, але не певну відповідь "немає гарантії для мови як такої". Все, що ми знаємо, - це те, що поточна реалізація GHC не пропустить оцінку такої функції.
Я зіткнувся з фактичною проблемою під час перенесення програми OCaml в Haskell. Початковий додаток мав взаємно рекурсивну структуру багатьох типів, і код оголошував ряд функцій, викликаних assert_structureN_is_correctN в 1..6 або 7, кожна з яких повертала одиницю, якщо структура справді була правильною, і кинула виняток, якщо її не було . Крім того, ці функції називали один одного, коли вони розкладали умови правильності. У Haskell це краще вирішувати, використовуючи Either Stringмонаду, тому я її так переписав, але питання як теоретичне питання залишилося. Дякую за всі матеріали та відповіді.
f 1"замінено" на undefinedвсі випадки.
... -> ()може 1) закінчуватись і повертатись (), 2) закінчуватися з помилкою виключення / часу виконання і нічого не повертати, або 3) розходитися (нескінченна рекурсія). GHC не оптимізує код, припускаючи, що може статися лише 1): якщо f 1вимагається, він не пропускає свою оцінку та повертається (). Семантика Haskell полягає в тому, щоб оцінити її і побачити, що відбувається серед 1,2,3.
()цьому питанні насправді немає нічого особливого (ні типу, ні значення). Все ті ж спостереження трапляються, якщо замінити () :: ()їх, скажімо, 0 :: Intскрізь. Це все просто нудні старі наслідки лінивої оцінки.
()типу, ()і undefined.
h1::()->() ; h1 () = ()таh2::()->() ; h2 _ = (). Запустітьh1 (f 1)і теh2 (f 1), і подивіться, що вимагає лише перший(f 1).