How to Rewrite Function Using Context Bounds? - scala

Given the following Addable type-class:
scala> trait Addable[A] {
| def add(x: A): A
| }
defined trait Addable
I created an instance for Int:
scala> class AddInt(x: Int) extends Addable[Int] {
| override def add(y: Int) = x + y
| }
defined class AddInt
Then, I created an implicit AddInt:
scala> implicit val addInt: AddInt = new AddInt(10)
addInt: AddInt = AddInt#1f010bf0
Lastly, I defined a generic function, foo:
scala> def foo[A](x: A)(implicit ev: Addable[A]): A = ev.add(x)
foo: [A](x: A)(implicit ev: Addable[A])A
Now, I can call it with the successful implicit resolution of addInt:
scala> foo(10)
res0: Int = 20
How can I define foo using the context bound notation?
example:
def foo[A : Addable]...?

Just define the method like you do in your own example:
def foo[A : Addable](x: A) = implicitly[Addable[A]].add(x)

Related

Method overloading in implicit class

I'm using a class (that I cannot modify) containing a method which receives a value of type Any as parameter, like the following example:
class Foo(value: Int) {
def +(other: Any): Foo = ???
}
I would like to add a custom implementation for the method +() when it's used with a specific type. I would expect to be able to do something like:
implicit class RichFoo(foo: Foo) {
def +(other: Int): Foo = ???
}
// or
implicit class RichFoo(foo: Foo) {
def +[T <: Bar](other: T): T = ???
}
However, these approaches don't work.
Is it possible to do without extending the original class?
No.
To the compiler, implicit conversions and other rewrite rules (like those around Dynamic) are a "last resort" of sorts. They are only applied if code does not already typecheck as-is. When you do foo + x, the compiler already knows that + takes Any, so it doesn't even try to look for implicits. If you did foo - x, and Foo had no - of the correct type, only then would the compiler search for a conversion.
Instead, you can create a method with a new name, maybe add, that is not present in Foo but is present in RichFoo. This will not, however, protect you from doing foo + 1 instead of foo add 1, since both methods are valid.
implicit class RichFoo(foo: Foo) {
def add(other: Int): Foo = ???
}
You can use a phantom type to track what is convertible.
scala> trait Tagged[B]
defined trait Tagged
scala> type Of[+A, B] = A with Tagged[B]
defined type alias Of
scala> class Tagger[B] { def apply[A](a: A): A Of B = a.asInstanceOf[A Of B] }
defined class Tagger
scala> object tag { def apply[B]: Tagger[B] = new Tagger[B] }
defined object tag
The given thing:
scala> case class C(i: Int) { def +(x: Any): C = C(i + x.toString.toInt) }
defined class C
and a marker trait:
scala> trait CC
defined trait CC
Normally:
scala> C(42) + "17"
res0: C = C(59)
This works:
scala> val cc = tag[CC](C(42))
cc: Of[C,CC] = C(42)
But not this:
scala> val cc = tag[CC](C(42): Any)
java.lang.ClassCastException: C cannot be cast to Tagged
... 29 elided
Maybe this:
scala> val cc = tag[CC](C(42): Serializable)
cc: Of[Serializable,CC] = C(42)
Then:
scala> implicit class XC(v: Serializable Of CC) {
| def +(x: Any): C Of CC = tag[CC] {
| println("OK")
| v.asInstanceOf[C] + x
| }}
defined class XC
Abnormally:
scala> val valueAdded = cc + "17"
OK
valueAdded: Of[C,CC] = C(59)
There's surely a better way to do this:
scala> implicit def untagit(x: Serializable Of CC): C Of CC = tag[CC](x.asInstanceOf[C])
untagit: (x: Of[Serializable,CC])Of[C,CC]
scala> cc.i
res9: Int = 42
because that ruins it:
scala> val res: C = cc + "17"
<console>:18: error: type mismatch;
found : <refinement>.type (with underlying type Of[Serializable,CC])
required: ?{def +(x$1: ? >: String("17")): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method XC of type (v: Of[Serializable,CC])XC
and method untagit of type (x: Of[Serializable,CC])Of[C,CC]
are possible conversion functions from <refinement>.type to ?{def +(x$1: ? >: String("17")): ?}
val res: C = cc + "17"
^
<console>:18: error: value + is not a member of Of[Serializable,CC]
val res: C = cc + "17"
^

How to override 'apply' in a Function with multiple parameter lists?

I'm trying to make an instance of this type of function object:
trait CanGetSiblingDock[S, D]
extends (D => String => S => Option[D])
with this:
implicit val getSiblingDock = new CanGetSiblingDock[Situation, Dock] {
def apply(dock: Dock)(siblingName: String)(sit: Situation): Option[Dock] = ???
}
The compiler objects:
error: object creation impossible, since method apply in trait Function1 of type (v1: FARG.Dock)String => (TestFARGModel4.this.Situation => Option[FARG.Dock]) is not defined
(Note that T1 does not match FARG.Dock)
implicit val getSiblingDock = new CanGetSiblingDock[Situation, Dock] {
^
If I understand this correctly, the compiler is complaining that the first argument of apply is not of type Dock. It appears to me, though, that it is.
Obviously, I'm misunderstanding something somewhere. How do you correctly make an instance of a Function with multiple parameter lists?
Something like:
scala> trait F extends (String => Int => Int)
defined trait F
scala> object X extends F { def apply(s: String): Int => Int = ??? }
defined object X
The type A => B => C is not Function2[A, B, C], for which the apply method would be def apply(a: A, b: B): C. But instead this is Function1[A, Function1[B, C]], like a curried function. If you want a Function2, you would have to write:
trait Foo extends Function2[Int, String, Boolean] {
override def apply(a: Int, b: String): Boolean = ???
}
If now you want multiple parameter lists, you would have to overload apply:
trait Foo extends Function2[Int, String, Boolean] {
override def apply(a: Int, b: String): Boolean = ???
def apply(a: Int)(b: String): Boolean = apply(a, b)
}
This is not possible because after erasure, both methods would look the same on the byte code level.

Alternative Syntax When Defining Implicit?

Given the following:
scala> trait Foo { def get: String = "get" }
defined trait Foo
I implemented it and made an implicit:
scala> case class FooImpl(x: String) extends Foo {
| override def get = s"got $x"
| }
defined class FooImpl
scala> implicit val fooImpl = FooImpl("yo")
fooImpl: FooImpl = FooImpl(yo)
Lastly, I tried to write a method that implicitly resolves a Foo, returning get on that implicitly resolved class.
scala> def f[A: Foo](x: A) = x.get
<console>:11: error: Foo does not take type parameters
def f[A: Foo](x: A) = x.get
^
<console>:11: error: value get is not a member of type parameter A
def f[A: Foo](x: A) = x.get
^
But I got the above errors.
So I re-wrote it using the implicit keyword:
scala> def f(implicit x: Foo): String = x.get
f: (implicit x: Foo)String
scala> f
res0: String = got yo
Is it possible to re-write this example to not explicitly specify the implicit keyword?
Note - it's possible that I'm confusing this notation with TypeTag under the section, Using a Context bound of a Type Parameter.
You are using the wrong syntax, what you want is an upper bound:
scala> def f[A <: Foo](x: A) = x.get
f: [A <: Foo](x: A)String
Where you're saying that A is a subtype of Foo and that tells the compiler that A does have a method called get.
The syntax you're using (:) means that there's an implicit conversion from A to Foo[A], the problem is that Foo doesn't take a type parameter, you can also check it into the REPL where the column syntax is translated to an implicit parameter:
scala> trait Foo2[T]
defined trait Foo2
scala> def g[T: Foo2](x: Int): Int = x
g: [T](x: Int)(implicit evidence$1: Foo2[T])Int

define implicit conversion from Int to Numeric in Scala

I want to be able to define the following function in Scala:
import Numeric.Implicits._
def f[T:Numeric](a:T) = a*2
but I get the error
error: could not find implicit value for parameter num: scala.math.Numeric[Any]
def f[T:Numeric](a:T) = a*2
^
I can get it to work with an implicit n:Numeric[T] argument and n.fromInt, but readability suffers. (The real code I'm trying to write is more complicated than this.)
I tried to define an implicit conversion from Int to Numeric[T]:
implicit def intToNumericT[T](x:Int)(implicit n:Numeric[T]):T = n.fromInt(x)
but that doesn't help. Is there a way to get the above code to work?
You could pimp a multiply-by-int method onto numeric types:
import Numeric.Implicits._
implicit class RichNumeric[A](val a: A) extends AnyVal {
def *(i: Int)(implicit n: Numeric[A]) = n.times(a, n.fromInt(i))
}
def f[T: Numeric](a: T) = a * 2
How about:
implicit class NumericInt(x:Int){
def nu[T](implicit n: Numeric[T]) = n.fromInt(x)
}
import Numeric.Implicits._
def f[T: Numeric](a: T) = a * 2.nu
Example:
scala> def f[T: Numeric](a: T) = a * 2.nu
f: [T](a: T)(implicit evidence$1: Numeric[T])T
scala> f(5)
res0: Int = 10
I think that definition should be as follows:
import Numeric.Implicits._
def f[T <% Numeric[T]#Ops](a: T)(implicit f: Int => T) = a * 2
println(f(5)) // 10
println(f(BigDecimal(7))) // 14
println(f(1.7)) // 3.4

varargs parameter as type parameter?

Is there any way to create something similar to this:
class F[A] {def apply(a: A) = println(a)}
So that I can:
(new F[Int*])(1,2,3)
UPDATE: but otherwise, I want F to accept normal parameters:
(new F[Int])(1)
scala> class F[A] { def apply(a: A*) = a.length }
defined class F
scala> val instance = new F[Int]
instance: F[Int] = F#11a6631
scala> instance(1,2,3,4,5)
res4: Int = 5