I'm new to Scala, and I'm running into this strange situation.
def bar[A, B](implicit foo: A => B): B = {
// do something
foo
}
And then I got error like
require B but found A => B
How should I get B form A => B
Here's the reason why I did this, I have two functions:
def funcA: String = {
def getStrA: String = "A"
// then there's the same operation in both functions
Try{ } match {
case Success(_) => getStrA
case Failure(_) => // exactlly same error handler in both function
}
}
def funcB: Int = {
def doSomething(x: Int): Int = {
// do something
x / 1
}
val x = 1
Try{ } match {
case Success(_) => doSomething(1)
case Failure(_) => // exactlly same error handler in both function
}
}
Here's what I want to achieve
def funcA: String = {
implicit def getStrA: String = "A"
bar
}
def funcB: Int = {
val x = 1
implicit def doSomething(x: Int): Int = {
// do something
x / 1
}
bar
}
def bar[A, B](implicit foo: A => B): B = {
Try{ } match {
case Success(_) => foo
case Failure(_) => // exactlly same error handler in both function
}
}
You have a conversion from A to B. You need to return B. The only way to do this is to pass A into the function. This signature has an implied assumption that you have some valid A value (most likely hardcoded) that you will always use here.
def bar[A, B](implicit foo: A => B): B = {
val a: A = ... // hmm...
foo(a)
}
Considering, that A is parametric, then you are either missing some information, or this A is impossible to create (it cannot be null because not all types can take null as a value), so you might need to throw exception in such case. Probably you are either missing some A provider or you should always fail this operation.
UPDATE:
There is no need for using implicits at all in your code:
def bar[B](f: onSuccess: A => B) =
Try{ some operations } match {
case Success(value) => onSuccess(value)
case Failure(_) => // error handler
}
def funcA = bar(_ => "A")
def funcB = bar(_ => 1)
import scala.reflect.runtime.universe._
val a: 42 = 42
val t: Type = typeOf[a.type]
assert(getConstantType(t).get =:= typeOf[42])
def getConstantType(t: Type): Option[ConstantType] = ???
How could I generally implement getConstantType so that the above assertion passes?
I assumed that something like this was possible since the assertion below passes:
assert(t <:< typeOf[42])
t.widen goes too far as it return Int. I'm looking for something that returns Int(42).
How about
assert(t.resultType =:= typeOf[42])
Updated -
def getConstantType[T](t: T): t.type = t
Update 2 -
def getConstantType(tp: Type): Option[ConstantType] = {
tp.erasure match {
case ConstantType(_) => Some(tp.erasure.asInstanceOf[ConstantType])
case _ => None
}
}
Try
def getConstantType(tp: Type): Option[ConstantType] = {
def unrefine(t: Type): Type = t.dealias match {
case RefinedType(List(t), scope) if scope.isEmpty => unrefine(t)
case t => t
}
unrefine(tp) match {
case SingleType(_, sym) => sym.typeSignature match {
case NullaryMethodType(t) => unrefine(t) match {
case c: ConstantType => Some(c)
case _ => None
}
case _ => None
}
case _ => None
}
}
Is there a more elegant way of doing this in scala?
def doTheDangerousThing(): Try[Result] = {
val result = Try(dangerousOp)
if (result.isFailure) {
println("error")
}
result
}
I think your if statement is perfectly valid. Here is another alternative:
def doTheDangerousThing(): Try[Result] = Try(dangerousOp) recoverWith {
case exception => println("error"); Failure(exception)
}
Something like this:
def doTheDangerousThing[Result](dangerousOp: =>Result): Try[Result] = Try(dangerousOp) match {
case o # Failure(_) => println("error"); o
case _ => _
}
Not sure if this is more idiomatic, but sometimes I find that placing the recoverWith in this manner improves readability for me:
def doDangerousThing(): Try[Result] = Try {
dangerousOp
} recoverWith {
case t: Throwable => println("error"); Failure(t)
}
My preferred,
def doTheDangerousThing(): Option[Result] = Try (dangerousOp) toOption
If the Try is successful you will get a Some(value), if it fails a None.
For a large compilation on Try uses, have a look at Try introduced in Scala 2.10.0 .
There are ways. For instance:
def doTheDangerousThing(): Try[Result] = {
val result = Try(dangerousOp)
result.failed foreach { _ =>
println("error")
}
result
}
Or, if you don't want to repeat result all through, then:
def doTheDangerousThing(): Try[Result] = {
Try(dangerousOp) recover {
case ex => println("error"); throw ex
}
}
Well, I suppose you could do something like this:
def doTheDangerousThing(): Option[Result] =
Try(dangerousOp) match {
case Success(result) => Some(result)
case Failure(e) => None //might want to log the error as well
}
In some cases I love to use two-step approach which will allow me a more granular error message control:
def retrieveData(dataId: String): Try[String] = {
Try {
Option(someApi(dataId))
.getOrElse(throw SomeApiFailedException("invalid dataId"))
} recoverWith {
case e: SomeApiFailedException => Failure(e)
case e: Throwable => Failure(SomeApiFailedException("failed retrieve dataId"))
}
}
case class SomeApiFailedException(err: String) extends RuntimeException(err)
I could choose from either of the three implementations, depending on whether I want to:
Simply propagate it upwards ( doTheDangerousThing1 )
Ignore the error ( doTheDangerousThing2 )
Intercept the error while propagating it upwards ( doTheDangerousThing3 )
Here is the code:
import scala.util.{Try,Success,Failure}
object temp {
type Result = Int
def dangerousOp = {
val r = scala.util.Random.nextInt(10)
if (r > 5) r else throw new RuntimeException("Failed on " + r)
}
def logMessage[T](t: T) = println(t)
def doTheDangerousThing1(): Try[Result] = Try(dangerousOp)
def doTheDangerousThing2(): Option[Result] = {
Try(dangerousOp) match {
case Success(r) => Option(r)
case _ => None
}
}
def doTheDangerousThing3(): Try[Result] = {
Try(dangerousOp) match {
case t # Success(r) => t
case t # _ => logMessage("failed: "+t); t
}
}
}
Inside the REPL
scala> doTheDangerousThing1
res0: scala.util.Try[Result] = Success(9)
scala> doTheDangerousThing1
res1: scala.util.Try[Result] = Success(9)
scala> doTheDangerousThing2
res2: Option[Result] = None
scala> doTheDangerousThing2
res3: Option[Result] = Some(7)
scala> doTheDangerousThing3
failed: Failure(java.lang.RuntimeException: Failed on 0)
res4: scala.util.Try[Result] = Failure(java.lang.RuntimeException: Failed on 0)
scala> doTheDangerousThing3
failed: Failure(java.lang.RuntimeException: Failed on 0)
res5: scala.util.Try[Result] = Failure(java.lang.RuntimeException: Failed on 0)
I'm using joda DateTime and UUID in my Play project. I'm struggling trying to put and get them from Postgresql:
import org.joda.time.DateTime
case class MyClass(id: Pk[UUID], name: String, addedAt: DateTime)
object MyClass {
val simple =
SqlParser.get[Pk[UUID]]("id") ~
SqlParser.get[String]("name") ~
SqlParser.get[DateTime]("added_at") map {
case id ~ name ~ addedAt => MyClass(id, name, addedAt)
}
implicit def rowToId = Column.nonNull[UUID] { (value, meta) =>
maybeValueToUUID(value) match {
case Some(uuid) => Right(uuid)
case _ => Left(TypeDoesNotMatch( s"Cannot convert $value: ${value.asInstanceOf[Any].getClass} to UUID"))
}
}
implicit def idToStatement = new ToStatement[UUID] {
def set(s: PreparedStatement, index: Int, aValue: UUID): Unit = s setObject(index, toByteArray(aValue))
}
def getSingle(id: UUID): Option[MyClass] = {
DB withConnection {
implicit con =>
SQL("SELECT my_table.id, my_table.name, my_table.added_at FROM my_table WHERE id = {id}")
.on('id -> id)
.as(MyClass.simple.*)
} match {
case List(x) => Some(x)
case _ => None
}
}
Implicit functions for joda DateTime are omited because they don't cause any error at this point. What causes an error is a getSingle(...) - conversion from and to UUID. The error is
org.postgresql.util.PSQLException: operator does not exist: uuid = bytea
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
4 helper functions:
private def maybeValueToUUID(value: Any): Option[UUID] = maybeValueToByteArray(value) match {
case Some(bytes) => Some(fromByteArray(bytes))
case _ => None
}
private def maybeValueToByteArray(value: Any): Option[Array[Byte]] =
try {
value match {
case bytes: Array[Byte] => Some(bytes)
case clob: Clob => None //todo
case blob: Blob => None //todo
case _ => None
}
} catch {
case e: Exception => None
}
def toByteArray(uuid: UUID) = {
val buffer = ByteBuffer.wrap(new Array[Byte](16))
buffer putLong uuid.getMostSignificantBits
buffer putLong uuid.getLeastSignificantBits
buffer.array
}
def fromByteArray(b: Array[Byte]) = {
val buffer = ByteBuffer.wrap(b)
val high = buffer.getLong
val low = buffer.getLong
new UUID(high, low)
}
Note that a record I'm trying to retrieve exists and has a correct format.
I have multiple Option's. I want to check if they hold a value. If an Option is None, I want to reply to user about this. Else proceed.
This is what I have done:
val name:Option[String]
val email:Option[String]
val pass:Option[String]
val i = List(name,email,pass).find(x => x match{
case None => true
case _ => false
})
i match{
case Some(x) => Ok("Bad Request")
case None => {
//move forward
}
}
Above I can replace find with contains, but this is a very dirty way. How can I make it elegant and monadic?
Edit: I would also like to know what element was None.
Another way is as a for-comprehension:
val outcome = for {
nm <- name
em <- email
pwd <- pass
result = doSomething(nm, em, pwd) // where def doSomething(name: String, email: String, password: String): ResultType = ???
} yield (result)
This will generate outcome as a Some(result), which you can interrogate in various ways (all the methods available to the collections classes: map, filter, foreach, etc.). Eg:
outcome.map(Ok(result)).orElse(Ok("Bad Request"))
val ok = Seq(name, email, pass).forall(_.isDefined)
If you want to reuse the code, you can do
def allFieldValueProvided(fields: Option[_]*): Boolean = fields.forall(_.isDefined)
If you want to know all the missing values then you can find all missing values and if there is none, then you are good to go.
def findMissingValues(v: (String, Option[_])*) = v.collect {
case (name, None) => name
}
val missingValues = findMissingValues(("name1", option1), ("name2", option2), ...)
if(missingValues.isEmpty) {
Ok(...)
} else {
BadRequest("Missing values for " + missingValues.mkString(", ")))
}
val response = for {
n <- name
e <- email
p <- pass
} yield {
/* do something with n, e, p */
}
response getOrElse { /* bad request /* }
Or, with Scalaz:
val response = (name |#| email |#| pass) { (n, e, p) =>
/* do something with n, e, p */
}
response getOrElse { /* bad request /* }
if ((name :: email :: pass :: Nil) forall(!_.isEmpty)) {
} else {
// bad request
}
I think the most straightforward way would be this:
(name,email,pass) match {
case ((Some(name), Some(email), Some(pass)) => // proceed
case _ => // Bad request
}
A version with stone knives and bear skins:
import util._
object Test extends App {
val zero: Either[List[Int], Tuple3[String,String,String]] = Right((null,null,null))
def verify(fields: List[Option[String]]) = {
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) =>
val u = i match {
case 0 => t copy (_1 = s)
case 1 => t copy (_2 = s)
case 2 => t copy (_3 = s)
}
Right(u)
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
val res = verify(List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify(List(name, Some("bob#bob.org"),pass))
res2.fold(fail, (consume _).tupled)
}
The same thing, using reflection to generalize the tuple copy.
The downside is that you must tell it what tuple to expect back. In this form, reflection is like one of those Stone Age advances that were so magical they trended on twitter for ten thousand years.
def verify[A <: Product](fields: List[Option[String]]) = {
import scala.reflect.runtime._
import universe._
val MaxTupleArity = 22
def tuple = {
require (fields.length <= MaxTupleArity)
val n = fields.length
val tupleN = typeOf[Tuple2[_,_]].typeSymbol.owner.typeSignature member TypeName(s"Tuple$n")
val init = tupleN.typeSignature member nme.CONSTRUCTOR
val ctor = currentMirror reflectClass tupleN.asClass reflectConstructor init.asMethod
val vs = Seq.fill(n)(null.asInstanceOf[String])
ctor(vs: _*).asInstanceOf[Product]
}
def zero: Either[List[Int], Product] = Right(tuple)
def nextProduct(p: Product, i: Int, s: String) = {
val im = currentMirror reflect p
val ts = im.symbol.typeSignature
val copy = (ts member TermName("copy")).asMethod
val args = copy.paramss.flatten map { x =>
val name = TermName(s"_$i")
if (x.name == name) s
else (im reflectMethod (ts member x.name).asMethod)()
}
(im reflectMethod copy)(args: _*).asInstanceOf[Product]
}
(zero /: fields.zipWithIndex) { (acc, v) => v match {
case (Some(s), i) => acc match {
case Left(_) => acc
case Right(t) => Right(nextProduct(t, i + 1, s))
}
case (None, i) =>
val fails = acc match {
case Left(f) => f
case Right(_) => Nil
}
Left(i :: fails)
}
}.asInstanceOf[Either[List[Int], A]]
}
def consume(name: String, email: String, pass: String) = Console println s"$name/$email/$pass"
def fail(is: List[Int]) = is map List("name","email","pass") foreach (Console println "Missing: " + _)
val name:Option[String] = Some("Bob")
val email:Option[String]= None
val pass:Option[String] = Some("boB")
type T3 = Tuple3[String,String,String]
val res = verify[T3](List(name,email,pass))
res.fold(fail, (consume _).tupled)
val res2 = verify[T3](List(name, Some("bob#bob.org"),pass))
res2.fold(fail, (consume _).tupled)
I know this doesn't scale well, but would this suffice?
(name, email, pass) match {
case (None, _, _) => "name"
case (_, None, _) => "email"
case (_, _, None) => "pass"
case _ => "Nothing to see here"
}