Не понимайте набора кондиционированных продолжений Скалы (@cpsparam [b, c])
-
19-09-2019 - |
Вопрос
Я изо всех сил пытаюсь понять, что именно это делает A @cpsParam[B,C]
И какие типы этой формы я должен назначить своим значениям при использовании объекта по разграниченным продолжениям.
Я посмотрел на некоторые источники:
http://lamp.epfl.ch/~rompf/continuations-icfp09.pdf
http://www.scala-lang.org/node/2096
http://dcsobral.blogspot.com/2009/07/delimited-continuations-explaiden-in.html
http://blog.richdougherty.com/2009/02/delimited-continuations-in-scala_24.html
Но они не дали мне особой интуиции в это. В последней ссылке автор пытается дать явное объяснение, но в любом случае это не достаточно ясно.
A здесь представляет выход вычисления, который также является входом в его продолжение. B представляет собой тип возврата этого продолжения, а C представляет его «окончательный» тип возврата - потому что сдвиг может сделать дальнейшую обработку до возвращаемого значения и изменить его тип.
Я не понимаю разницы между «выходом вычислений», «Возвратом типа продолжения» и «Окончательным типом возврата продолжения». Они звучат как синонимы.
Решение
Итак, люди помогли мне с этим в другом месте. Вот ответ:
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({...})
.
Другие советы
Я все еще нахожусь в процессе выяснения точных правил/последствий для печати, связанных здесь.
Кажется легким/простым, если типы в примерах «достаточно просты», чтобы «хорошо соответствовать», как показано выше, но он становится более междоулистым/трудным (по крайней мере для меня) в сравнении с вещами с типированием, давая 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
дано в определении карты в статье Тиарка.
Что мне не хватает повторения, чтобы понять здесь?
Есть советы/идеи?