Понимание 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, описанные в конце статьи, которые имеют различную семантику. "Вызывающий" должен выбрать, какой метод перезапуска использовать. Им обоим необходим доступ к внутренним данным субконтинуации, поэтому они не могут оперировать представлением субконтинуации как функции.