How to pass implicit parameter explicitly? - scala

If we define the following function:
def methodWithImplicit(explicit: String)(implicit imp: String) = {
println(explicit + imp)
}
we can call it as follows:
methodWithImplicit("abc")("efg") //abc - explicit, efg - imp
And it works fine. Now consider the following TypeClass:
trait MyTypeClass[T] {
def accept(t: T): T
}
which is going to be used inside extractor object:
object TestExtractor {
def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
if (!str.isEmpty)
Some(myTypeClass.accept(str))
else
None
}
So if we use it as follows:
implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
override def accept(t: String): Unit = t
}
"123" match {
case TestExtractor(str) => println(str)
}
It works ok. But how to pass the parameter explicitly when using with pattern matching? I tried
"123" match {
case TestExtractor(str)(myTypeClass) => println(str) //compile error
}
and
"123" match {
case TestExtractor(myTypeClass)(str) => println(str) //compile error
}
But it does not compile.

Since the left hand side seems to accept essentially nothing but trees built from stable identifiers, constant literals, and lower-case letters for variable names, I don't see any way to get closer to the desired syntax than this:
val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)
"hello" match {
case `TestExtractor(myTypeClass)`(str) => println(str)
}
This of course requires that you define the weirdly named value TestExtractor(myTypeClass) (in backticks) right before the match-case, so you can use it as a single symbol.
Full code:
trait MyTypeClass[T] {
def accept(t: T): T
}
object TestExtractor { outer =>
def unapply(str: String)(implicit myTypeClass: MyTypeClass[String]): Option[String] =
if (!str.isEmpty)
Some(myTypeClass.accept(str))
else
None
class ExplicitTestExtractor(tc: MyTypeClass[String]) {
def unapply(t: String) = outer.unapply(t)(tc)
}
def apply(tc: MyTypeClass[String]): ExplicitTestExtractor =
new ExplicitTestExtractor(tc)
}
implicit val myTypeClass:MyTypeClass[String] = new MyTypeClass[String] {
override def accept(t: String): String = t.toUpperCase
}
val `TestExtractor(myTypeClass)` = TestExtractor(myTypeClass)
"hello" match {
case `TestExtractor(myTypeClass)`(str) => println(str)
}

Related

How to implement typesafe domain repository in scala?

I want to implement generic and typesafe domain repository. Say I have
trait Repo[Value] {
def put(value: Value): Unit
}
case class IntRepo extends Repo[Int] {
override def put(value: Int): Unit = ???
}
case class StringRepo extends Repo[String] {
override def put(value: String): Unit = ???
}
case class DomainRepo(intRepo: IntRepo, stringRepo: StringRepo) {
def putAll[?](values: ?*): Unit // what type should be here?
}
As result I want to have following api:
domainRepo.putAll(1, 2, 3, "foo", "bar") //Should work
domainRepo.putAll(1, 2, true, "foo") // should not compile because of boolean value
The question is How to achieve this?
so, I see only one way to make it typesafe. It's to do pattern matching on Any type like
def putAll(values: Seq[Any]) => Unit = values.foreach {
case str: String => stringRepo.put(str)
case int: Int => intRepo.put(int)
case _ => throw RuntimeException // Ha-Ha
}
but what if I would have 10000 of types here? it would be a mess!
another not clear for me approach for now is to use dotty type | (or) like following:
type T = Int | String | 10000 other types // wouldn't be a mess?
def putAll(t: T*)(implicit r1: Repo[Int], r2: Repo[String] ...) {
val myTargetRepo = implicitly[Repo[T]] // would not work
}
so, what do you think? is it even possible?
the easies way I've saw was
Map[Class[_], Repo[_]]
but this way allows to do a lot of errors
It seems you are looking for a type class
trait Repo[Value] {
def put(value: Value): Unit
}
implicit val intRepo: Repo[Int] = new Repo[Int] {
override def put(value: Int): Unit = ???
}
implicit val stringRepo: Repo[String] = new Repo[String] {
override def put(value: String): Unit = ???
}
case object DomainRepo {
def putAll[Value](value: Value)(implicit repo: Repo[Value]): Unit = repo.put(value)
}
If you want domainRepo.putAll(1, 2, 3, "foo", "bar") to compile and domainRepo.putAll(1, 2, true, "foo") not to compile, you can try to use heterogeneous collection (HList).
import shapeless.{HList, HNil, ::, Poly1}
import shapeless.ops.hlist.Mapper
trait Repo[Value] {
def put(value: Value): Unit
}
implicit val intRepo: Repo[Int] = new Repo[Int] {
override def put(value: Int): Unit = ???
}
implicit val stringRepo: Repo[String] = new Repo[String] {
override def put(value: String): Unit = ???
}
case object DomainRepo {
def put[Value](value: Value)(implicit repo: Repo[Value]): Unit = repo.put(value)
object putPoly extends Poly1 {
implicit def cse[Value: Repo]: Case.Aux[Value, Unit] = at(put(_))
}
def putAll[Values <: HList](values: Values)(implicit
mapper: Mapper[putPoly.type, Values]): Unit = mapper(values)
}
DomainRepo.putAll(1 :: 2 :: 3 :: "foo" :: "bar" :: HNil)
// DomainRepo.putAll(1 :: 2 :: true :: "foo" :: HNil) // doesn't compile

Combine two functions under the same name without overloading

Here is the code:
def transform1(f: String => String): Unit = {
val s = getString
f.andThen(putString)(s)
}
def transform2(f: String => Option[String]): Unit = {
val s = getString
f(s).foreach(putString(_))
}
How do you express these two ideas in one single function?
Method overloading does not work and seems discouraged by the community.
I didn't understand that why anyone may want this but here is a way to do it:
def transform(f: Either[(String => String), (String => Option[String])]: Unit = f match {
case Left(f) => // do transform1 here
case Right(f) => //do transform2 here
}
As I said at the begining you probably shouldn't want to do this; perhaps you should directly ask what you want.
The pattern to avoid overloading is to convert disparate arguments to a common, specific type. There could be any number of such conversions.
Not sure this is the most compelling example, however.
object X {
trait MapFlat[-A, +B] { def apply(x: A): B }
implicit class mapper[A](val f: A => A) extends MapFlat[A, A] {
override def apply(x: A) = {
val res = f(x)
println(res)
res
}
}
implicit class flatmapper[A](val f: A => Option[A]) extends MapFlat[A, Option[A]] {
override def apply(x: A) = {
val res = f(x)
res foreach println
res
}
}
def f[B](g: MapFlat[String, B]) = {
g("abc")
}
}
object Test extends App {
import X._
f((s: String) => s)
f((s: String) => Some(s))
}
One way to do it will be type classes, here's a sample -
trait Transformer[T] {
def transform(foo: String => T)
}
object Transformer {
implicit object StringTransformer extends Transformer[String] {
override def transform(foo: (String) => String): Unit = ??? // Your logic here
}
implicit object OptStringTransformer extends Transformer[Option[String]] {
override def transform(foo: (String) => Option[String]): Unit = ??? // Your logic here
}
}
class SampleClass {
def theOneTransformYouWant[T: Transformer](f: String => T) = {
implicitly[Transformer[T]].transform(f)
}
def canUseBothWays(): Unit = {
theOneTransformYouWant((s: String) => s)
theOneTransformYouWant((s: String) => Some(s))
}
}
Another way would be the magnet pattern
http://spray.io/blog/2012-12-13-the-magnet-pattern/
sealed trait TransformationMagnet {
def apply(): Unit
}
object TransformationMagnet {
implicit def fromString(f: String => String): TransformationMagnet =
new TransformationMagnet {
def apply(): Unit = ??? // Your code goes here
}
implicit def fromOptString(f: String => Option[String]): TransformationMagnet =
new TransformationMagnet {
def apply(): Unit = ??? // your code goes here
}
}
class SampleClass {
def theOneTransformYouWant(f: TransformationMagnet) = {
???
}
def hereWeUseItInBothWays(): Unit = {
theOneTransformYouWant((s: String) => s)
theOneTransformYouWant((s: String) => Some(s))
}
}
add a new parameter on the description typeOfTransform
add a conditional inside the function
if (typeOfTransform == type1){
//functionality1
}else {
//functionality2
}
Just for completeness, you can actually overload methods like this by adding implicit arguments which will always be available:
def transform(f: String => Option[String]): Unit = ...
def transform(f: String => String)(implicit d: DummyImplicit): Unit = ...

Can a Scala "extractor" use generics on unapply?

Can't I use a generic on the unapply method of an extractor along with an implicit "converter" to support a pattern match specific to the parameterised type?
I'd like to do this (Note the use of [T] on the unapply line),
trait StringDecoder[A] {
def fromString(string: String): Option[A]
}
object ExampleExtractor {
def unapply[T](a: String)(implicit evidence: StringDecoder[T]): Option[T] = {
evidence.fromString(a)
}
}
object Example extends App {
implicit val stringDecoder = new StringDecoder[String] {
def fromString(string: String): Option[String] = Some(string)
}
implicit val intDecoder = new StringDecoder[Int] {
def fromString(string: String): Option[Int] = Some(string.charAt(0).toInt)
}
val result = "hello" match {
case ExampleExtractor[String](x) => x // <- type hint barfs
}
println(result)
}
But I get the following compilation error
Error: (25, 10) not found: type ExampleExtractor
case ExampleExtractor[String] (x) => x
^
It works fine if I have only one implicit val in scope and drop the type hint (see below), but that defeats the object.
object Example extends App {
implicit val intDecoder = new StringDecoder[Int] {
def fromString(string: String): Option[Int] = Some(string.charAt(0).toInt)
}
val result = "hello" match {
case ExampleExtractor(x) => x
}
println(result)
}
A variant of your typed string decoder looks promising:
trait StringDecoder[A] {
def fromString(s: String): Option[A]
}
class ExampleExtractor[T](ev: StringDecoder[T]) {
def unapply(s: String) = ev.fromString(s)
}
object ExampleExtractor {
def apply[A](implicit ev: StringDecoder[A]) = new ExampleExtractor(ev)
}
then
implicit val intDecoder = new StringDecoder[Int] {
def fromString(s: String) = scala.util.Try {
Integer.parseInt(s)
}.toOption
}
val asInt = ExampleExtractor[Int]
val asInt(Nb) = "1111"
seems to produce what you're asking for. One problem remains: it seems that trying to
val ExampleExtractor[Int](nB) = "1111"
results in a compiler crash (at least inside my 2.10.3 SBT Scala console).

Casting String to Int using scala extractors

I am trying to cast a String to Int using extractors. My code looks as follows.
object Apply {
def unapply(s: String): Option[Int] = try {
Some(s.toInt)
} catch {
case _: java.lang.Exception => None
}
}
object App {
def toT[T](s: AnyRef): Option[T] = s match {
case v: T => Some(v)
case _ => None
}
def foo(param: String): Int = {
//reads a Map[String,String] m at runtime
toT[Int](m("offset")).getOrElse(0)
}
}
I get a runtime error: java.lang.String cannot be cast to java.lang.Integer. It seems the extractor is not being used at all. What should I do?
Edit: My use case is as follows. I am using play and I want to parse the query string passed in the url. I want to take the query string value (String) and use it as an Int, Double etc. For example,
val offset = getQueryStringAs[Int]("offset").getOrElse(0)
I think the biggest problem here is, that you seem to confuse casting and conversion. You have a Map[String, String] and therefore you can't cast the values to Int. You have to convert them. Luckily Scala adds the toInt method to strings through implicit conversion to StringOps.
This should work for you:
m("offset").toInt
Note that toInt will throw a java.lang.NumberFormatException if the string can not be converted to an integer.
edit:
What you want will afaik only work with typeclasses.
Here is an example:
trait StringConverter[A] {
def convert(x: String): A
}
implicit object StringToInt extends StringConverter[Int] {
def convert(x: String): Int = x.toInt
}
implicit object StringToDouble extends StringConverter[Double] {
def convert(x: String): Double = x.toDouble
}
implicit def string2StringConversion(x: String) = new {
def toT[A](implicit ev: StringConverter[A]) = ev.convert(x)
}
usage:
scala> "0.".toT[Double]
res6: Double = 0.0
There's a problem in your code, for which you should have received compiler warnings:
def toT[T](s: AnyRef): Option[T] = s match {
case v: T => Some(v) // this doesn't work, because T is erased
case _ => None
}
Now... where should Apply have been used? I see it declared, but I don't see it used anywhere.
EDIT
About the warning, look at the discussions around type erasure on Stack Overflow. For example, this answer I wrote on how to get around it -- though it's now deprecated with Scala 2.10.0.
To solve your problem I'd use type classes. For example:
abstract class Converter[T] {
def convert(s: String): T
}
object Converter {
def toConverter[T](converter: String => T): Converter[T] = new Converter[T] {
override def convert(s: String): T = converter(s)
}
implicit val intConverter = toConverter(_.toInt)
implicit val doubleConverter = toConverter(_.toDouble)
}
Then you can rewrite your method like this:
val map = Map("offset" -> "10", "price" -> "9.99")
def getQueryStringAs[T : Converter](key: String): Option[T] = {
val converter = implicitly[Converter[T]]
try {
Some(converter convert map(key))
} catch {
case ex: Exception => None
}
}
In use:
scala> getQueryStringAs[Int]("offset")
res1: Option[Int] = Some(10)
scala> getQueryStringAs[Double]("price")
res2: Option[Double] = Some(9.99)

scala: how to implement this matcher in specs2

I have the following method:
def save(entity: A): Either[List[Error],A] + {....
which I want to test using specs2
I want to test for the existence of a specific error when a required field is not specified, like this:
val noNickname = User(
nickname = "",
name = "new name",
)
noNickname.save must beLeft.like {
case errors => {
atLeastOnceWhen(errors) {
case error => {
error.errorCode must equalTo(Error.REQUIRED)
error.field must equalTo("nickname")
}
}
}
}
It works fine, but I'd like to define my own matcher to make it less verbose, like this:
noNickname.save must haveError.like {
case error => {
error.errorCode must equalTo(Error.REQUIRED)
error.field must equalTo("nickname")
}
}
}
I had a look at the documentation (http://etorreborre.github.com/specs2/guide/org.specs2.guide.Matchers.html#Matchers) but I can't figure out how to define a custom matcher like haveError.like
Here your code with a few changes to make it compile:
case class Error(errorCode: String, field: String)
def save[A](entity: A): Either[List[Error],A] = Left(List(Error("REQUIRED", "nickname")))
case class User(nickname: String, name: String)
val noNickname = User(nickname = "", name = "new name")
"save noNickName" >> {
save(noNickname) must haveError.like {
case error => {
error.errorCode must equalTo("REQUIRED")
error.field must equalTo("nickname")
}
}
}
def haveError[T] = new ErrorMatcher[T]
class ErrorMatcher[T] extends Matcher[Either[List[T], _]] {
def apply[S <: Either[List[T], _]](value: Expectable[S]) =
result(value.value.left.toOption.isDefined,
value.description + " is Left",
value.description + " is not Left",
value)
def like[U](f: PartialFunction[T, MatchResult[U]]) =
this and partialMatcher(f)
private def partialMatcher[U](f: PartialFunction[T, MatchResult[U]]) =
new Matcher[Either[List[T], _]] {
def apply[S <: Either[List[T], _]](value: Expectable[S]) = {
// get should always work here because it comes after the "and"
val errors = value.value.left.toOption.get
val res = atLeastOnceWhen[T, U](errors)(f)
result(res.isSuccess,
value.description+" is Left[T] and "+res.message,
value.description+" is Left[T] but "+res.message,
value)
}
}
}
Notice that the matcher is defined on Either[List[T], _] everywhere.
I'm also wondering about the failure messages that are returned in case you don't find the expected error message, they might not be very explicit when the partial function fails.
So you may want to aim for using a contain matcher. Like this:
"save noNickName" >> {
save(noNickname) must haveError.containing(Error("REQUIRED", "nickname"))
}
// I'm reusing the beLeft matcher here
def haveError[T]: Matcher[Either[List[T], _]] = beLeft
// and using an implicit conversion to extend it
implicit def toErrorListMatcher[T](m: Matcher[Either[List[T], _]]): ErrorListMatcher[T] =
new ErrorListMatcher[T](m)
class ErrorListMatcher[T](m: Matcher[Either[List[T], _]]) {
def containing(t: T) =
// the 'contain' matcher is adapted to take in an
// Either[List[T], _] and work on its left part
m and contain(t) ^^ ((e: Either[List[T], _]) => e.left.toOption.get)
}
[Update]
The first solution (using atLeastOnceWhen and a partial function) can be combined with the second one (using an implicit) and the beLike matcher, to get maximum reusability of existing specs2 code:
def haveError[T]: Matcher[Either[List[T], _] = beLeft
implicit def toErrorListMatcher[T](m: Matcher[Either[List[T], _]]): ErrorListMatcher[T] =
new ErrorListMatcher[T](m)
class ErrorListMatcher[T](m: Matcher[Either[List[T], _]]) {
// beLike checks one element
// beLike.atLeastOnce transforms that matcher on a
// matcher on a sequence of elements
def like[S](f: PartialFunction[T, MatchResult[S]]) = {
m and beLike(f).atLeastOnce ^^ ((e: Either[List[T], _]) => e.left.toOption.get)
}