I'm trying out Scala's union types defined in this Miles Sabin's blog post:
http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/
and also discussed in
How to define "type disjunction" (union types)?
For the simple case defined there they work ok, but what I'm trying to do is use them to make a generic JSON parser in Play Framework that would only accept certain values (String, Boolean, Int, Undefined) and then pass them successfully.
Here is my code:
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}."))
}
}
Which I would then like to use in this manner:
def update(code: String) = Action.async(parse.json) {
request =>
withValue(request) { (field, value) =>
// Code that does something with the value
Future(Ok)
}
}
But my withValue function gives a compile error:
[error] found : Some[String]
[error] required: T
[error] case (x: JsString, y: JsString) => block(x.value.toString, Some(y.value.toString))
Shouldn't T be UpdateType which should accept Some[String] or is there something I'm not getting here?
Any idea what I could do here to get these working or is it possible? I'm quite new to the more advanced types and type lambdas in Scala but I'm trying learn how they work to create more type safe code.
I also noticed that Miles Sabin has a library called Shapeless (https://github.com/milessabin/shapeless) which I was looking into, but couldn't find anything there that would do the same thing as I'm trying to achieve here.