Я пробую объединить типы Scala, определенные в этой записи блога Майлза Сабина:
http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/
а также обсуждается в
Как определить дизъюнкцию типов (типы объединения)?
Для простого случая, определенного там, они работают нормально, но я пытаюсь использовать их для создания общего парсера JSON в Play Framework, который будет принимать только определенные значения (String, Boolean, Int, Undefined), а затем успешно передавать их .
Вот мой код:
type UpdateType = Option[String] |∨| Option[Int] |∨| Option[Boolean] |∨| Option[List[Int]]
def withValue[T : (UpdateType)#λ](request: Request[JsValue])(block: (String, T) => Future[SimpleResult]) = {
val field = request.body \ ("field")
val value = request.body \ ("value")
(field, value) match {
case (x: JsString, y: JsString) => block(x.value.toString, Some(y.value.toString))
case (x: JsString, y: JsNumber) => block(x.value.toString, Some(y.value.intValue))
case (x: JsString, y: JsBoolean) => block(x.value.toString, Some(y.value.booleanValue))
case (x: JsString, y: JsUndefined) => block(x.value.toString, None)
case _ => Future.successful(BadRequest(s"Incorrect field, value pair for ${request.body}."))
}
}
Который я затем хотел бы использовать таким образом:
def update(code: String) = Action.async(parse.json) {
request =>
withValue(request) { (field, value) =>
// Code that does something with the value
Future(Ok)
}
}
Но моя функция withValue выдает ошибку компиляции:
[error] found : Some[String]
[error] required: T
[error] case (x: JsString, y: JsString) => block(x.value.toString, Some(y.value.toString))
Разве T не должен быть UpdateType, который должен принимать Some [String], или я чего-то не понимаю?
Есть идеи, что я могу сделать здесь, чтобы они работали, или это возможно? Я новичок в более продвинутых типах и лямбдах типов в Scala, но я пытаюсь понять, как они работают, чтобы создать более безопасный код.
Я также заметил, что у Майлза Сабина есть библиотека под названием Shapeless (https://github.com/milessabin/shapeless), который я искал, но не смог найти там ничего, что могло бы сделать то же самое, что я пытаюсь достичь здесь.
Option[String]
, либо наOption[Int]
, и из-за стирания типа вы не сможете отличить их друг от друга. Это определенно не более типобезопасный код. Лучшим решением было бы объявить вашу собственную коллекцию классов, происходящих от общего подкласса, по одному для каждого из типов, которые вы объединяете, и по одному для заменыNone
. На самом деле это более строгая типизация, потому что у вас есть свои собственные конкретные типы для этого варианта использования, а не повторное использованиеOption
. - person wingedsubmariner   schedule 30.04.2014sealed
, компилятор может проверить, не забыли ли вы какие-либо типы. OO действительно является правильным способом сделать это в Scala, программирование на уровне типов предназначено для людей, которым нужно выставлять напоказ, но оно не относится к производственному коду. - person wingedsubmariner   schedule 30.04.2014