Понимание API для мульти-строки с разделителями продолжения


API для многопрограммных разделенных продолжений описывается в статьеразделенное управление в OCaml, абстрактно и конкретно системное описание .

Мой вопрос касается типа push_subcont : ('a,'b) subcont -> (unit -> 'a) -> 'b. Почему этот тип не ('a,'b) subcont -> 'a -> 'b? Кроме того, почему существует отдельный тип для подсознания: почему не просто ('a,'b) subcont = 'a -> 'b? Я почти уверен, что для этого есть веская причина, потому что Олег делает вещи максимально элегантными (но не более элегантными).

Спасибо!

1 5

1 ответ:

Почему бы и нет ('a,'b) subcont -> 'a -> 'b?

Я думаю, что это по той же причине, что и для push_prompt - что легче понять. push_prompt p (fun () -> e) интуитивно является формой try e with p: приглашение p помещается в стек в качестве обработчика, и e выполняется под этим обработчиком. Если вы используете push_prompt p e вместо этого, строгий язык сначала вычислит аргументы p и e, а e запустится и "вызовет исключения" до того, как будет задано приглашение.

push_subcont sk (fun () -> e) может иметь те же проблемы: это своего рода, интуитивно, "перезапустить вычисление sk, прерванное исключением". Важно, что e выполняется внутри контекста вычисления, а не вне его, например, если он хочет вызвать исключения, соответствующие обработчикам, установленным sk.

Почему бы просто не ('a,'b) subcont = 'a -> 'b?

Это можно было бы сделать, если бы существовал только один способ перезапуска субконтинуаций: они могли бы быть возвращены "предварительно перезапущенными", в виде функций, которые при применении перезапускаются с заданным аргумент.

Но это не так: есть push_subcont и push_delim_subcont, описанные в конце статьи, которые имеют различную семантику. "Вызывающий" должен выбрать, какой метод перезапуска использовать. Им обоим необходим доступ к внутренним данным субконтинуации, поэтому они не могут оперировать представлением субконтинуации как функции.