Ответ 1
Scala не имеет более высокого ранга полиморфизма, хотя вы можете имитировать его с некоторыми искажениями (см. здесь и здесь). Хорошая новость заключается в том, что здесь не нужна такая огневая мощь. Попробуйте следующее:
def runOption[A](ctx: => A @cps[Option[A]]): Option[A] = reset(Some(ctx))
def get[A](value:Option[A]) = shift { k:(A=>Option[A]) => value flatMap k }
Вторая попытка
Хорошо, попробуйте еще раз, в свете вашего примера, используя более одного типа в блоке runOption
:
object BO {
import scala.util.continuations._
def runOption[A](ctx: => A @cps[Option[A]]): Option[A] = reset(Some(ctx))
def get[A, B](value:Option[A]):A @cps[Option[B]] = shift { k:(A=>Option[B]) =>
value flatMap k
}
class CPSOption[A](o:Option[A]) {
def value[B] = get[A, B](o)
}
implicit def opt2cpsopt[A](o:Option[A]) = new CPSOption[A](o)
def test1 = runOption {
val x = get[Int, Int](None)
x
}
def test2 = runOption {
Some(1).value[Int]
}
def test3 = runOption {
val x = Some(1)
val y = Some(2)
x.value[Int] + y.value[Int]
}
def test_fn(x:Option[Int], y:Option[Int], z:Option[Int]) =
runOption (x.value[Int] * x.value[Int] +
y.value[Int] * y.value[Int] +
z.value[Int] * z.value[Int])
def test4 = test_fn(Some(1), Some(2), Some(3))
def test5 = test_fn(Some(1), None, Some(3))
def test6 = runOption { val x = Some(1)
val y = Some(2)
x.value[Boolean] == y.value[Boolean] }
}
К сожалению, как вы можете видеть, результаты не очень хороши. Из-за Scala возможности вывода с ограниченным типом вам необходимо предоставить явный тип типа для большинства применений value
, а в любом данном блоке runOption
он всегда будет одним и тем же параметром для каждого использования value
- см. test_fn
, где это становится довольно ужасно. С другой стороны, вам больше не нужно указывать явный параметр типа для блока runOption
, но это довольно маленькая победа в сравнении. Таким образом, теперь это полностью безопасно, но это не то, что я бы назвал удобным для пользователя, и я предполагаю, что удобство для пользователя было точкой этой библиотеки.
Я по-прежнему убежден, что типы ранга-n здесь неприменимы. Как вы можете видеть, проблема здесь в том, что теперь существует одна из типов реконструкции, а типы ранга-типа затрудняют реконструкцию, а не меньше!