How to remove PartialFunction input bound - scala

Is there any way to convert PartialFunction[Int,_] to PartialFunction[Any,_] ?
Following code throws ClassCastException
val f: PartialFunction[Int, _] = ...
f.asInstanceOf[PartialFunction[Any,Any]].isDefinedAt("a")

Wrap it in a new partial function which is undefined for inputs that aren't of type Int:
val g: PartialFunction[Any, Any] = { case x: Int if f isDefinedAt x => f(x) }

You can wrap your partial function in a new PartialFunction, as has already been suggested:
val g: PartialFunction[Any, Any] = {
case x: Int if f isDefinedAt x => f(x)
}
Another option is to extend PartialFunction and manually override apply and isDefined. You can even do this with an anonymous class. For example:
new PartialFunction[Any, Any] {
def apply(x: Any) = f(x.asInstanceOf[Int])
def isDefinedAt(x: Any) = x.isInstanceOf[Int] && f.isDefinedAt(x.asInstanceOf[Int])
}
You might also play with Function.unlift and PartialFunction.lift, or PartialFunction.condOpt:
import Function._
val g = unlift[Any, Any] {
case x: Int => f.lift(x)
case _ => None
}
//Alternative with condOpt
import PartialFunction._
val g = unlift(condOpt(_ : Any) { case x: Int => f.lift(x) }.flatten)
If this is common enough, you might even enrich PartialFunction with the desired method:
implicit class RichPartialFunction(val pf: PartialFunction[Int, Any]) extends AnyVal {
implicit def withAnyDomain = new PartialFunction[Any, Any] {
def apply(x: Any) = pf(x.asInstanceOf[Int])
def isDefinedAt(x: Any) = x.isInstanceOf[Int] && pf.isDefinedAt(x.asInstanceOf[Int])
}
}

Related

How to convert one partial function to another?

Suppose I've got partial function parf
val parf: PartialFunction[Int, String] = { case 0 => "!!!" }
Now I've got also case class A(x: Int) and I need a function to transform PartialFunction[Int, String] to PartialFunction[A, String]:
def foo(pf: PartialFunction[Int, String]): PartialFunction[A, String] = ???
For example, foo(parf) should return {case A(0) => "!!!" }. How would you write function foo ?
To maintain the correct functionality, you need to check if the inner partial function is defined on a parameter you're going to pass:
val parf: PartialFunction[Int, String] = { case 0 => "!!!" }
case class A(x: Int)
def foo(pf: PartialFunction[Int, String]): PartialFunction[A, String] = {
case A(i) if pf.isDefinedAt(i) => pf(i)
}
If you plan to do it on a larger scale, you might want to convert a partial function to an extractor object, so it can be used in pattern matches directly with a better syntax:
trait Extractor[A, B] {
def unapply(a: A): Option[B]
}
object Extractor {
implicit def partialFunctionAsExtractor[A, B](pf: PartialFunction[A, B]): Extractor[A, B] =
new Extractor[A, B] {
def unapply(a: A) = if (pf.isDefinedAt(a)) Some(pf(a)) else None
}
}
def foo2(pf: Extractor[Int, String]): PartialFunction[A, String] = {
case A(pf(str)) => str
}
foo2(parf) // implicit conversion magic
I don't see what got you confused about it? You just need to match-extract the Int out of A and then let the PF behave as it wants to behave.
scala> case class A(x: Int)
// defined class A
scala> val parf: PartialFunction[Int, String] = { case 0 => "!!!" }
// parf: PartialFunction[Int,String] = <function1>
scala> def foo(pf: PartialFunction[Int, String]): PartialFunction[A, String] = {
| case A(x) if pf.isDefinedAt(x) => pf(x)
| }
// foo: (pf: PartialFunction[Int,String])PartialFunction[A,String]
scala> val parfA = foo(parf)
// parfA: PartialFunction[A,String] = <function1>
scala> parfA(A(0))
//res0: String = !!!
scala> parfA(A(1))
// scala.MatchError: A(1) (of class A)
// at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:254)
// at scala.PartialFunction$$anon$1.apply(PartialFunction.scala:252)
// at $anonfun$1.applyOrElse(<console>:11)
// at $anonfun$1.applyOrElse(<console>:11)
// at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:34)
// at $anonfun$foo$1.applyOrElse(<console>:13)
// at $anonfun$foo$1.applyOrElse(<console>:13)
// at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:34)
// ... 28 elided
#Oleg Pyzhcov already provided a great solution. Another approach would be to create a PartialFunction[A, Int] that is defined at A(0), and use andThen to chain it with parf:
val parf: PartialFunction[Int, String] = { case 0 => "!!!" }
case class A(n: Int)
val bar: PartialFunction[A, Int] = { case a: A if a.n == 0 => a.n }
def foo(pf: PartialFunction[Int, String]): PartialFunction[A, String] =
bar andThen pf
// foo: (pf: PartialFunction[Int,String])PartialFunction[A,String]
foo(parf)
// res1: PartialFunction[A,String] = <function1>

writing a custom get method for a scala map

I have a map which is something like
val m = Map("foo" -> "bar", "faz" -> "baz")
I need to write a custom get method, so that the key can be the key in the map with a number in the end.
So for example:
m.get("foo1") should return "bar"
I am looking for a good scala pattern to solve this problem.
Also I am generating the above map from a for loop using yield, so I can't do something like this
val m = CustomMap("foo" -> "bar")
Any solutions will be appreciated.
Thanks
First of all, you can generate a map from a for comprehension, and then convert it to CustomMap. You just need to define a
def apply(map: Map[String, String]) = CustomMap(map.toSeq :_*) in CustomMap - then you can do val m = CustomMap( for { ... } yield ... )
Secondly, if it doesn't have to be named get (it probably shouldn't be anyway), you can do this sort of thing with an implicit:
object PimpMyMap {
val pref = ".*?(\\d+)".r
implicit class Pimped[V](val map: Map[String,V]) extends AnyVal {
def getPrefix(key: String): Option[V] = map.get(key).orElse { key match {
case pref(k) => map.get(k)
case _ => None
}
}
Now you can write things like:
import PimpMyMap._
val map = Map("foo" -> 1)
val one = map.getPrefix("foo123") // Some(1)
val anotherOne = map.getPrefix("foo") // also Some(1);
You can do this with an implicit class and implicit conversion:
import scala.language.implicitConversions
object MapHelpers {
implicit def optionStringToString(maybeS: Option[String]): String = maybeS.getOrElse("")
implicit class MapWithIntKey(val m: Map[String, String]) extends Map[String, String] {
override def get(key: String): Option[String] = {
val intRegex = """(\d+)""".r
val keyWithoutInt = intRegex
.findFirstMatchIn(key)
.map(int => {
val idx = key.indexOf(int.toString)
key.slice(0, idx)
})
.getOrElse(key)
m.get(keyWithoutInt)
}
def +[V1 >: String](
kv: (String, V1)): scala.collection.immutable.Map[String, V1] = m + kv
def -(key: String): scala.collection.immutable.Map[String, String] = m - key
def iterator: Iterator[(String, String)] = m.iterator
}
}
object App {
import MapHelpers._
def testMapImplicit(): Unit = {
val myMap: MapWithIntKey = Map("foo" -> "bar", "faz" -> "baz")
val result: String = myMap.get("foo1")
println("result", result) // bar
}
}
Working Scastie
If you have a sure way to get the real key from the fake key, you can do this with Map.withDefault:
class CustomMap[K, +V] private (underlying: Map[K, Option[V]]) {
def get(k: K): Option[V] = underlying(k)
}
object CustomMap {
def apply[K, V](original: Map[K, V], keyReducer: K => K) = new CustomMap(originalMap.
mapValues(Some(_)).
withDefault(k => originalMap.get(keyReducer(k))
)
}
In your case, you can use this with
val stringKeyReducer: String => String = k.reverse.dropWhile(_.isDigit).reverse
to drop the digits at the end of your strings, so
CustomMap(Map("foo" -> "bar"), stringKeyReducer).get("foo1") = Some("bar")
Here is solution which combines both the answers.
import scala.language.implicitConversions
object MapHelpers {
implicit def optionStringToString(maybeS: Option[String]): String = maybeS.getOrElse("")
implicit class MapWithIntKey(val m: Map[String, String]) extends Map[String, String] {
override def get(key: String): Option[String] = {
val prefix = "(.*?)\\d+".r
m.get(key).orElse{
key match {
case prefix(p) => m.get(p)
case _ => None
}
}
}
def +[V1 >: String](kv: (String, V1)): scala.collection.immutable.Map[String, V1] = m + kv
def -(key: String): scala.collection.immutable.Map[String, String] = m - key
def iterator: Iterator[(String, String)] = m.iterator
}
}
object App {
import MapHelpers._
def testMapImplicit(): Unit = {
val myMap: MapWithIntKey = Map("foo" -> "bar", "faz" -> "baz")
println("result - number match ", myMap.get("foo1"))
println("result - exact match ", myMap.get("foo"))
}
}
App.testMapImplicit()
Working Scastie

Reinstalling type parameters from prefix in a macro expansion

The following should show the problem:
class Container[A](val xs: List[A]) {
def foo(fun: A => A)(implicit ord: Ordering[A]): List[A] =
macro ContainerMacros.fooImpl // how to pass `xs`?
}
object ContainerMacros {
def fooImpl(c: blackbox.Context)
(fun: c.Expr[Nothing => Any])
(ord: c.Expr[Ordering[_]]): c.Expr[List[Nothing]] = {
import c.universe._
reify {
// val cont = c.prefix.splice.asInstanceOf[Container[_]]
// cont.xs.map(fun.splice).sorted(ord.splice)
???
}
}
}
That is, there seems no way to add A as a type parameter to fooImpl (if I do that, the compiler complains). So I have to remove it, but then the question is how to get the things in reify working the intended way, i.e. how to reintroduce the missing type parameter A.
Here is an attempt:
def fooImpl(c: blackbox.Context)
(fun: c.Expr[Nothing => Any])
(ord: c.Expr[Ordering[_]]): c.Expr[List[Nothing]] = {
import c.universe._
reify {
val ext = c.prefix.splice.asInstanceOf[ExtensionTest[_]]
import ext.{A1 => A}
val extC = ext .asInstanceOf[ExtensionTest[A]]
val funC = fun.splice.asInstanceOf[A => A]
val ordC = ord.splice.asInstanceOf[Ordering[A]]
val xs = extC.xs.asInstanceOf[List[A]] // computer says no
xs.map(funC).sorted(ordC)
}
}
The xs.map(funC) doesn't work with one of those legendary scalac error messages:
Error:(27, 16) type mismatch;
found : _$2 => Any where type _$2
required: Any => ?
xs.map(funC).sorted(ordC)
Answer actually thanks to #edmundnoble via Scala Gitter channel:
You can add type parameters in the impl call, thus it's possible to pass the A from Container to the macro expansion:
class Container[A](val xs: List[A]) {
def foo(fun: A => A)(implicit ord: Ordering[A]): List[A] =
macro ContainerMacros.fooImpl[A]
}
object ContainerMacros {
def fooImpl[A](c: blackbox.Context)
(fun: c.Expr[A => A])
(ord: c.Expr[Ordering[A]])
(implicit t: c.WeakTypeTag[A]): c.Expr[List[A]] = {
import c.universe._
reify {
val extC = c.prefix.splice.asInstanceOf[Container[A]]
val funC = fun.splice
val ordC = ord.splice
val xs = extC.xs
xs.map(funC).sorted(ordC)
}
}
}

Scala: Are these two partial functions equivalent?

Are these two partial functions equivalent?
val f0: PartialFunction[Int, String] = {
case 10 => "ten"
case n: Int => s"$n"
}
val f1 = new PartialFunction[Int, String] {
override def isDefinedAt(x: Int): Boolean = true
override def apply(v: Int): String = if (v == 10) "ten" else s"$v"
}
UPD
val pf = new PartialFunction[Int, String] {
def isDefinedAt(x: Int) = x == 10
def apply(v: Int) = if (isDefinedAt(v)) "ten" else "undefined"
}
def fun(n: Int)(pf: PartialFunction[Int, String]) = pf.apply(n)
println(fun(100)(pf))
Is it truly PF now?
I think you need 2 partial (value) functions to use the PartialFunction the way it is designed to be: one for the value 10, and the other for the other Ints:
val f0:PartialFunction[Int, String] = { case 10 => "ten" }
val fDef:PartialFunction[Int, String] = { case n => s"$n" }
And how to apply them:
val t1 = (9 to 11) collect f0
t1 shouldBe(Array("ten"))
val t2 = (9 to 11) map (f0 orElse fDef)
t2 shouldBe(Array("9", "ten", "11"))

Overcoming Scala Type Erasure For Function Argument of Higher-Order Function

Essentially, what I would like to do is write overloaded versions of "map" for a custom class such that each version of map differs only by the type of function passed to it.
This is what I would like to do:
object Test {
case class Foo(name: String, value: Int)
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map(func: Int => Int) = Foo(f.name, func(f.value))
def map(func: String => String) = Foo(func(f.name), f.value)
}
def main(args: Array[String])
{
def square(n: Int): Int = n * n
def rev(s: String): String = s.reverse
val f = Foo("Test", 3)
println(f.string)
val g = f.map(rev)
val h = g.map(square)
println(h.string)
}
}
Of course, because of type erasure, this won't work. Either version of map will work alone, and they can be named differently and everything works fine. However, it is very important that a user can call the correct map function simply based on the type of the function passed to it.
In my search for how to solve this problem, I cam across TypeTags. Here is the code I came up with that I believe is close to correct, but of course doesn't quite work:
import scala.reflect.runtime.universe._
object Test {
case class Foo(name: String, value: Int)
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map[A: TypeTag](func: A => A) =
typeOf[A] match {
case i if i =:= typeOf[Int => Int] => f.mapI(func)
case s if s =:= typeOf[String => String] => f.mapS(func)
}
def mapI(func: Int => Int) = Foo(f.name, func(f.value))
def mapS(func: String => String) = Foo(func(f.name), f.value)
}
def main(args: Array[String])
{
def square(n: Int): Int = n * n
def rev(s: String): String = s.reverse
val f = Foo("Test", 3)
println(f.string)
val g = f.map(rev)
val h = g.map(square)
println(h.string)
}
}
When I attempt to run this code I get the following errors:
[error] /src/main/scala/Test.scala:10: type mismatch;
[error] found : A => A
[error] required: Int => Int
[error] case i if i =:= typeOf[Int => Int] => f.mapI(func)
[error] ^
[error] /src/main/scala/Test.scala:11: type mismatch;
[error] found : A => A
[error] required: String => String
[error] case s if s =:= typeOf[String => String] => f.mapS(func)
It is true that func is of type A => A, so how can I tell the compiler that I'm matching on the correct type at runtime?
Thank you very much.
In your definition of map, type A means the argument and result of the function. The type of func is then A => A. Then you basically check that, for example typeOf[A] =:= typeOf[Int => Int]. That means func would be (Int => Int) => (Int => Int), which is wrong.
One of ways of fixing this using TypeTags looks like this:
def map[T, F : TypeTag](func: F)(implicit ev: F <:< (T => T)) = {
func match {
case func0: (Int => Int) #unchecked if typeOf[F] <:< typeOf[Int => Int] => f.mapI(func0)
case func0: (String => String) #unchecked if typeOf[F] <:< typeOf[String => String] => f.mapS(func0)
}
}
You'd have to call it with an underscore though: f.map(rev _). And it may throw match errors.
It may be possible to improve this code, but I'd advise to do something better. The simplest way to overcome type erasure on overloaded method arguments is to use DummyImplicit. Just add one or several implicit DummyImplicit arguments to some of the methods:
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map(func: Int => Int)(implicit dummy: DummyImplicit) = Foo(f.name, func(f.value))
def map(func: String => String) = Foo(func(f.name), f.value)
}
A more general way to overcome type erasure on method arguments is to use the magnet pattern. Here is a working example of it:
sealed trait MapperMagnet {
def map(foo: Foo): Foo
}
object MapperMagnet {
implicit def forValue(func: Int => Int): MapperMagnet = new MapperMagnet {
override def map(foo: Foo): Foo = Foo(foo.name, func(foo.value))
}
implicit def forName(func: String => String): MapperMagnet = new MapperMagnet {
override def map(foo: Foo): Foo = Foo(func(foo.name), foo.value)
}
}
implicit class FooUtils(f: Foo) {
def string = s"${f.name}: ${f.value}"
// Might be simply `def map(func: MapperMagnet) = func.map(f)`
// but then it would require those pesky underscores `f.map(rev _)`
def map[T](func: T => T)(implicit magnet: (T => T) => MapperMagnet): Foo =
magnet(func).map(f)
}
This works because when you call map, the implicit magnet is resolved at compile time using full type information, so no erasure happens and no runtime type checks are needed.
I think the magnet version is cleaner, and as a bonus it doesn't use any runtime reflective calls, you can call map without underscore in the argument: f.map(rev), and also it can't throw runtime match errors.
Update:
Now that I think of it, here magnet isn't really simpler than a full typeclass, but it may show the intention a bit better. It's a less known pattern than typeclass though. Anyway, here is the same example using the typeclass pattern for completeness:
sealed trait FooMapper[F] {
def map(foo: Foo, func: F): Foo
}
object FooMapper {
implicit object ValueMapper extends FooMapper[Int => Int] {
def map(foo: Foo, func: Int => Int) = Foo(foo.name, func(foo.value))
}
implicit object NameMapper extends FooMapper[String => String] {
def map(foo: Foo, func: String => String) = Foo(func(foo.name), foo.value)
}
}
implicit class FooUtils(f: Foo) {
def string = s"${f.name}: ${f.value}"
def map[T](func: T => T)(implicit mapper: FooMapper[T => T]): Foo =
mapper.map(f, func)
}