Понимание API для мульти-строки с разделителями продолжения
API для многопрограммных разделенных продолжений описывается в статьеразделенное управление в OCaml, абстрактно и конкретно системное описание .
Мой вопрос касается типа push_subcont : ('a,'b) subcont -> (unit -> 'a) -> 'b
. Почему этот тип не ('a,'b) subcont -> 'a -> 'b
? Кроме того, почему существует отдельный тип для подсознания: почему не просто ('a,'b) subcont = 'a -> 'b
? Я почти уверен, что для этого есть веская причина, потому что Олег делает вещи максимально элегантными (но не более элегантными).
Спасибо!
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
, описанные в конце статьи, которые имеют различную семантику. "Вызывающий" должен выбрать, какой метод перезапуска использовать. Им обоим необходим доступ к внутренним данным субконтинуации, поэтому они не могут оперировать представлением субконтинуации как функции.