Не понимаю типизацию продолжений Scala с разделителями (A @cpsParam [B, C]) - PullRequest
22 голосов
/ 13 марта 2010

Я изо всех сил пытаюсь понять, что именно это означает, когда значение имеет тип A @cpsParam[B,C] и какие типы этой формы я должен назначить своим значениям при использовании средства продолжения с разделителями.

Я смотрел на некоторые источники:

http://lamp.epfl.ch/~rompf/continuations-icfp09.pdf

http://www.scala -lang.org / узел / 2096

http://dcsobral.blogspot.com/2009/07/delimited-continuations-explained-in.html

http://blog.richdougherty.com/2009/02/delimited-continuations-in-scala_24.html

но они не дали мне особой интуиции в этом. В последней ссылке автор пытается дать четкое объяснение, но оно все равно недостаточно ясно.

Здесь A представляет результат вычисления, который также является входом для его продолжения. B представляет тип возврата этого продолжения, а C представляет его «окончательный» тип возврата, потому что shift может выполнить дальнейшую обработку возвращаемого значения и изменить его тип.

Я не понимаю разницу между "выходом вычисления", "типом возврата продолжения" и "окончательным типом возврата продолжения". Они звучат как синонимы.

Ответы [ 2 ]

20 голосов
/ 14 марта 2010

Итак, люди помогли мне с этим в другом месте. Вот ответ:

reset ({
    ...
    ...shift((k:A=>B) => ...::C)::A...
    ...
}::B)::C

Итак, shift - это дыра типа A в вычислении {...} типа B. Аргумент shift возвращает значение типа C, и поэтому reset ({...}) имеет тип C.

Ключевым трюком в понимании этого материала было то, что {...} и reset {...} имеют разный тип в зависимости от того, какой тип возвращает аргумент shift.

Например:

reset ({
    "number "+shift((k:Int=>String) => List(k(1), k(2), k(3)))
})

возвращает List("number 1", "number 2", "number 3").

Здесь A равно Int, B равно String, C равно List[String], поскольку {"number" + _} (здесь) является функцией от Int до String и аргументом shift, учитывая эту функцию, выдает List[String], который становится результатом reset({...}).

1 голос
/ 16 ноября 2010

Я все еще нахожусь в процессе выяснения точных правил / значений печатания, вовлеченных здесь.

Кажется, легко / легче, если типы в примерах "достаточно просты", чтобы "хорошо вписаться", как показано выше, но это становится более интересным / трудным (по крайней мере для меня) при сравнении вещей с типизацией, которую дает tiark rompf:

|- e: A@cpsParam[B,C]; {[|r|]}: U
-----------------------------------------------------
[|val x: A = e; r|] = [|e|].map( (x: A) => {[|r|]} )

, поэтому результат [|e|].map( (x: A) => {[|r|]} ) будет иметь тип Shift[U,B,C] в соответствии с определением карты, приведенным в статье Тиарка.

Здесь U не обязательно совпадает с B.

Пока я не понимаю, почему U может отличаться от B без чего-то вроде U <: B приведено в определении карты в статье Тиарка.

Что я упускаю из виду, что не могу понять здесь?

Какие-нибудь советы / идеи?

...