Я играю с каким-то DSL, определяемым монадическим интерфейсом.
Поскольку применение монады с использованием нескольких приложений flatMap довольно обременительно, и синтаксически синтаксически я не понимаю, чтоЯ пытаюсь неявно смешивать монадический и не монадический код, используя продолжения с разделителями.
Это на самом деле работает нормально, но я действительно не доволен типами, потому что я должен ограничивать себя типом "Любой"сделать при компиляции :(. Таким образом, использование «Any» и «casting» позже, когда потребуется результат, может привести к ошибкам во время выполнения ...
Вот пример кода для смешивания Option-Monad в Scala собычный код, чтобы вы могли видеть, о чем я говорю:
object BO {
import scala.util.continuations._
def runOption[C](ctx: => Any @cpsParam[Option[Any],Option[Any]]): Option[C] = {
val tmp : Option[Any] = reset {
val x : Any = ctx
Some(x)
}
tmp.asInstanceOf[Option[C]]
}
def get[A](value:Option[A]) = shift { k:(A=>Option[Any]) =>
value.flatMap(k)
}
class CPSOption[A](o:Option[A]) {
def value = get[A](o)
}
implicit def opt2cpsopt[A](o:Option[A]) = new CPSOption(o)
def test1 = runOption[Int] {
val x = get(None)
x
}
def test2 = runOption[Int] {
val x = Some(1).value
x
}
def test3 = runOption[Int] {
val x = Some(1)
val y = Some(2)
x.value + y.value
}
def test_fn(x:Option[Int], y:Option[Int], z:Option[Int]) = runOption[Int] {
x.value * x.value + y.value * y.value + z.value * z.value
}
def test4 = test_fn(Some(1), Some(2), Some(3))
def test5 = test_fn(Some(1), None, Some(3))
}
скомпилируйте код с помощью: $ scalac -P: продолжений: включите BO.scala
и протестируйте в scala REPL:
scala> import BO._
scala> test4
res0: Option[Int] = Some(14)
scala> test5
res1: Option[Int] = None
Option-Monad запускается с использованием функции runOption (см. Функции тестирования). Функции, вызываемые внутри runOption , могут использовать get function или метод value для получения значения из Option .Если значение равно Нет , монада немедленно остановится и вернет Нет .Так что больше нет необходимости в сопоставлении с образцом для значения типа Option .
Проблема в том, что мне нужно использовать тип "Any" в runOption идля типа продолжения в get .
Можно ли выразить runOption и get с типами ранга n в scala?Так что я могу написать:
def runOption[C](ctx: forall A . => A @cpsParam[Option[A], Option[C]]) : Option[C] =
...
def get[A](value:Option[A]) = shift { k:(forall B . A=>Option[B]) =>
value.flatMap(k)
}
Спасибо!