programming - scala pagina oficial
No entiendo la escritura de las continuaciones delimitadas de Scala(A @cpsParam[B, C]) (2)
Me A @cpsParam[B,C]
entender qué significa exactamente cuando un valor tiene el tipo A @cpsParam[B,C]
y qué tipos de este formulario debo asignar a mis valores cuando uso la función de continuaciones delimitadas.
He mirado algunas fuentes:
http://lamp.epfl.ch/~rompf/continuations-icfp09.pdf
http://www.scala-lang.org/node/2096
http://dcsobral.blogspot.com/2009/07/delimited-continuations-explained-in.html
http://blog.richdougherty.com/2009/02/delimited-continuations-in-scala_24.html
pero no me dieron mucha intuición en esto. En el último enlace, el autor intenta dar una explicación explícita, pero de todos modos no está lo suficientemente claro.
La A aquí representa la salida del cálculo, que también es la entrada para su continuación. La B representa el tipo de retorno de esa continuación, y la C representa su tipo de retorno "final", porque shift puede hacer un procesamiento adicional al valor devuelto y cambiar su tipo.
No entiendo la diferencia entre "salida del cálculo", "tipo de retorno de la continuación" y "tipo de retorno final de la continuación". Suenan como sinónimos.
Entonces, la gente me ayudó con este en otro lugar. Aquí está la respuesta:
reset ({
...
...shift((k:A=>B) => ...::C)::A...
...
}::B)::C
Entonces, shift
es un agujero de tipo A
en un cómputo {...}
de tipo B
El argumento de shift
devuelve un valor de tipo C
y es por eso que reset ({...})
tiene el tipo C
El truco clave para entender esto fue ver que {...}
y reset {...}
tienen un tipo diferente dependiendo de qué tipo devuelve el argumento del shift
.
Por ejemplo:
reset ({
"number "+shift((k:Int=>String) => List(k(1), k(2), k(3)))
})
List("number 1", "number 2", "number 3")
devoluciones List("number 1", "number 2", "number 3")
.
Aquí A
es Int
, B
es String
, C
es List[String]
porque {"number" + _}
es (aquí) una función de Int
a String
y el argumento de shift
, dada esa función, produce un List[String]
, que se convierte en resultado del reset({...})
.
Todavía estoy en el proceso de averiguar las reglas / implicaciones de mecanografía exactas involucradas aquí.
Parece fácil / más fácil si los tipos en los ejemplos son "lo suficientemente simples" para "ajustarse bien" como se muestra arriba, pero se vuelve más interesante / difícil (al menos para mí) al comparar las cosas con la tipificación que da tiark rompf:
|- e: A@cpsParam[B,C]; {[|r|]}: U
-----------------------------------------------------
[|val x: A = e; r|] = [|e|].map( (x: A) => {[|r|]} )
por lo tanto, el resultado de [|e|].map( (x: A) => {[|r|]} )
tendrá el tipo Shift[U,B,C]
acuerdo con la definición de mapa que figura en el documento de tiark.
Aquí U no es necesariamente lo mismo que B.
Hasta ahora no entiendo por qué se permite que U sea diferente de B sin algo como U <: B
dado en la definición de mapa en el artículo de tiark.
¿Qué es lo que me estoy perdiendo repsectivamente no entiendo aquí?
¿Algún consejo / ideas?