I'm interested if I can create method with similar idea:
def myMethod[T](param: T)(implicit oneOf: Either[TypeClass1[T], TypeClass2[T]]) = oneOf match ...
I've tried to use default parameters (I've seen somethin similar in akka):
def myMethod[T](param: T)(implicit t1: TypeClass1[T] = null, t2: TypeClass2[T] = null) =
if (t1 == null) ...
However, that way I cannot force scala compiler to find at least one of them.
Also, I've implemented implicit conversion from TypeClass1[T] to Left[TypeClass1[T], TypeClass2[T]] and from TC2 to Right, however Scala compiler ignores this conversions.
Is there any way to do something like this?
The obvious solution is to create a new typeclass that can be constructed using either TypeClass1 or TypeClass2. The new typeclass implements the functionality used by myMethod that is common to both and maps it to the appropriate methods on TypeClass1 or TypeClass2.
Here is an example:
trait TypeClass1[T] {
def showOne = println("Typeclass 1")
}
trait TypeClass2[T] {
def showTwo = println("Typeclass 2")
}
trait UnionTypeClass[T] {
def show
}
object UnionTypeClass {
implicit def t1[T](implicit ev: TypeClass1[T]) = new UnionTypeClass[T] {
def show = ev.showOne
}
implicit def t2[T](implicit ev: TypeClass2[T]) = new UnionTypeClass[T] {
def show = ev.showTwo
}
}
implicit object IntClass extends TypeClass1[Int]
implicit object StringClass extends TypeClass2[String]
def myMethod[T](param: T)(implicit ev: UnionTypeClass[T]) = {
ev.show
}
myMethod(0)
myMethod("hello")
This will print
Typeclass 1
Typeclass 2
In Scala 3 you might be able to use union type like so
trait Foo[A]
trait Bar[A]
given foo as Foo[Int] {}
def g[T](using Foo[T] | Bar[T]) = summon
foo[Int] // ok
You can use standard shapeless.OrElse or implicitbox.Priority or implicitlogic.Or from one of libraries
https://github.com/milessabin/shapeless
https://github.com/monix/implicitbox
https://github.com/Jasper-M/implicitlogic
def myMethod[T](param: T)(implicit oneOf: OrElse[TypeClass1[T], TypeClass2[T]]) = ???
// def myMethod[T](param: T)(implicit oneOf: Priority[TypeClass1[T], TypeClass2[T]]) = ???
// def myMethod[T](param: T)(implicit oneOf: Or[TypeClass1[T], TypeClass2[T]]) = ???
trait TypeClass1[T]
trait TypeClass2[T]
implicit val tc1: TypeClass1[Int] = ???
implicit val tc2: TypeClass2[String] = ???
myMethod(1) //compiles
myMethod("a") //compiles
Type classes OrElse, Priority are similar to UnionTypeClass from #Tim's answer but they prioritize t1, t2.
Related
Let's say I have a function such as:
def foo[T<:U <:V](t:T): Unit
I want to know if there is a way of combining these two in a type W so that I can have:
def foo[T<: W](t: T): Unit
The use case for this is:
trait FooTrait{
type W
def foo[T<: W](t: T): Unit
}
I might have two different implementations of foo, one of them with a simple W1 type bound whereas the other one is T<:W1 <:W2 I want the more complex one to define a W3 so that I can have:
def foo[T<: W3](t: T): Unit
Similiarly, I want to be able to do these with type classes. So if I have:
def bar[T<:U :V](t:T): Unit
I want to have
def bar[T:X](t:T): Unit
The use case for this is essentially the same as the earlier case.
is this possible?
In the first part of your question, the syntax isn't even valid.
If you want to impose multiple upper bounds U, V on some type T,
you have to use with keyword anyway:
trait A
trait B
def f[X <: A with B](x: X): Unit = ???
This here doesn't work:
// def f[X <: A <: B](x: X): Unit = ??? // doesn't compile
To address the second part of your question, I would like to
explain why something like with doesn't work for typeclasses.
This here does work:
trait Foo[X]
trait Bar[X]
def g[X: Foo : Bar](x: X): Unit = ???
This here doesn't work:
// def g[X: Foo with Bar](x: X): Unit = ??? // nope
Why? Because
def foo[X: Y](x: X): Ret = ???
is actually a shortcut for
def foo[X](x: X)(implicit y: Y[X]): Ret = ???
If you would try to somehow amalgamate two different typeclasses Foo and Bar,
this would result in the following desugared code:
def foo[X](x: X)(implicit superPowerfulThing: (Foo somehowGluedWith Bar)[X]): Ret = ???
But this is obviously not something that you should want.
Instead, what you want is:
def foo[X](x: X)(implicit foo: Foo[X], bar: Bar[X])(x: X): Ret = ???
In this way, the two requirements Foo and Bar can be supplied independently,
which wouldn't work if you requested some superPowerfulThing that implements
both Foo and Bar at once.
Hope that clarifies why something works or doesn't work.
Andrey Tyukin has correctly point out that with is probably the answer for your first question and that the second question has no direct solution. However if you are OK with indirect solutions, you might work this around by introducing a new type class that will says that the target types belongs to the two original type classes. Here is a simple example for imaginary typeclasses Foo and Bar and for a base trait Base with a specific implementation ChildFooBar:
trait Foo[X] {
def doFoo(x: X): String
}
trait Bar[X] {
def doBar(x: X): String
}
trait Base {
type W[_]
def baz[T: W](t: T): String
}
class ChildFooBar extends Base {
import ChildFooBar._
type W[X] = FooAndBar[X]
override def baz[T: FooAndBar](t: T): String = {
val foo = implicitly[Foo[T]]
val bar = implicitly[Bar[T]]
foo.doFoo(t) + bar.doBar(t)
}
}
object ChildFooBar {
#implicitNotFound("The type should provide both implicit Foo and implicit Bar.")
case class FooAndBar[X](foo: Foo[X], bar: Bar[X])
object FooAndBar {
implicit def fromFooAndBar[X](implicit foo: Foo[X], bar: Bar[X]): FooAndBar[X] = FooAndBar(foo, bar)
}
// private is important here to avoid diversion of implicits
private implicit def toFoo[X](implicit fooAndBar: FooAndBar[X]): Foo[X] = fooAndBar.foo
private implicit def toBar[X](implicit fooAndBar: FooAndBar[X]): Bar[X] = fooAndBar.bar
}
Now if SomeClass is a member of both Foo and Bar typeclasses, then
case class SomeClass(foo: Int, bar: Double)
object SomeClass {
implicit val foo: Foo[SomeClass] = new Foo[SomeClass] {
override def doFoo(x: SomeClass) = s"foo = ${x.foo}"
}
implicit val bar: Bar[SomeClass] = new Bar[SomeClass] {
override def doBar(x: SomeClass) = s"bar = ${x.bar}"
}
}
the simple code
println(new ChildFooBar().baz(SomeClass(1, 2.0)))
will compile and work as expected.
Let's say we have the following traits:
trait MyValue
object MyValue {
case class MyBoolean(record: Boolean) extends MyValue
case class MyLong(record: Long) extends MyValue
}
trait MyValueExtractor[T] {
def apply(record: T): Option[MyValue]
}
trait MyThing[T] {
def name: String
def myValueExtractor: MyValueExtractor[T]
def myValue(record: T): Option[MyValue] = myValueExtractor(record)
}
What I want is something like this but without the second type parameter.
Note: I can't actually update the MyThing trait; I'm just using this as an illustration of the intended functionality.
trait MyThing[T, U] {
def name: String
def myValueExtractor: MyValueExtractor[T]
def myValue(record: T): Option[MyValue] = myValueExtractor(record)
def myRelatedValue(record: T): Option[U]
}
I'm wondering if I could use the type class pattern to help solve this (i.e., import some rich class that implicitly gives me a myRelatedValue method)?
Here's the rub. Every time T (above) is MyValue.MyBoolean, U must be a String. Every time T is MyValue.MyLong, U must be a Double. In other words, there's a sort of underlying mapping between T and U.
Is there a good way to do this using type class?
Sure. You just need to define some Mapping typeclass with implementations for your desired pairs of types. Then MyThing can have a method that takes an implicit typeclass instance and simply invokes its method.
Here's the code (I removed the unneeded details)
// types
case class MyBoolean(record: Boolean)
case class MyLong(record: Long)
// trait which uses the Mapping typeclass
trait MyThing[T] {
def myRelatedValue[U](record: T)(implicit ev: Mapping[T, U]): Option[U] = ev.relatedValue(record)
}
// typeclass itself
trait Mapping[T, U] {
def relatedValue(record: T): Option[U]
}
object Mapping {
implicit val boolStringMapping = new Mapping[MyBoolean, String] {
def relatedValue(record: MyBoolean) = Some(record.record.toString)
}
implicit val longDoubleMapping = new Mapping[MyLong, Double] {
def relatedValue(record: MyLong) = Some(record.record)
}
}
// usage
val myBoolThing = new MyThing[MyBoolean] {}
val myLongThing = new MyThing[MyLong] {}
val myStringThing = new MyThing[String] {}
myBoolThing.myRelatedValue(MyBoolean(true)) // Some(true)
myLongThing.myRelatedValue(MyLong(42L)) // Some(42.0)
myStringThing.myRelatedValue("someString") // error: could not find implicit value
Note that e.g. myBoolThing.myRelatedValue(MyBoolean(true)) will yield a type Option[U]. However, since myRelatedValue is parameterized, you can help the compiler and invoke it as myBoolThing.myRelatedValue[String](MyBoolean(true)), in which case you will obtain an Option[String]. If you try something other than String for MyBoolean, you will get an error.
Is it possible to constrain a Scala generic type to only types that have overloaded a specific operator?
Example:
def foo[T](...):T = {...}
foo(...) * .70
Searching Google has yet to produce a solution. I considered restricting T to be of type Numeric (or scala's equivalent), but then I want to allow users to define custom types and specify their own behaviors for these operators.
Use a typeclass.
trait Multiply[A] {
def multiply(x: A, y: Double): A
}
object Multiply {
def apply[A](implicit instance: Multiple[A]): Multiply[A] = instance
trait Ops[A] {
def typeClassInstance: Multiply[A]
def self: A
def *(y: Double): A = typeClassInstance.multiply(self, y)
}
trait ToMultiplyOps {
implicit def toMultiplyOps[A](target: A)(implicit tc: Multiply[A]): Ops[A] = new Ops[A] {
val self = target
val typeClassInstance = tc
}
}
trait AllOps[A] extends Ops[A] {
def typeClassInstance: Multiply[A]
}
object ops {
implicit def toAllMultiplyOps[A](target: A)(implicit tc: Multiply[A]): AllOps[A] = new AllOps[A] {
val self = target
val typeClassInstance = tc
}
}
}
(Note that this is equivalent to what's generated by Michael Pilquist's simulacrum library, so you don't really need all this boilerplate)
Then your users can do this:
case class Foo(x: Int)
object Foo {
implicit val multiplyFoo: Multiply[Foo] = new Multiply[Foo] {
def multiply(foo: Foo, y: Double): Foo = ???
}
}
Foo(42) * 3.1415
Yes, there are so-called structural types. You can define them as follows:
def foo[T <: {def yourOperator:Unit}(...) : T = {...}
where yourOperator is the name of the method definition and Unit the return type. In this example T will accept every type which is declaring a method called yourOperator with Unit as return type.
This could be used for example to handle a resource which is Closeable. Imagine the following code.
def operatorOnResource[T <: {def close : Unit}](resource: T) : Unit = {
//do stuff with the resource
resource.close
}
Please note that this example is also kind of a risk, because T has only constraints on its structure. Hence, even if T satisfies the structural needs the semantic of the close could be different.
Given a simple parametrized type like class LK[A], I can write
// or simpler def tagLK[A: TypeTag] = typeTag[LK[A]]
def tagLK[A](implicit tA: TypeTag[A]) = typeTag[LK[A]]
tagLK[Int] == typeTag[LK[Int]] // true
Now I'd like to write an analogue for class HK[F[_], A]:
def tagHK[F[_], A](implicit ???) = typeTag[HK[F, A]]
// or some other implementation?
tagHK[Option, Int] == typeTag[HK[Option, Int]]
Is this possible? I've tried
def tagHK[F[_], A](implicit tF: TypeTag[F[_]], tA: TypeTag[A]) = typeTag[HK[F, A]]
def tagHK[F[_], A](implicit tF: TypeTag[F], tA: TypeTag[A]) = typeTag[HK[F, A]]
but neither works for the obvious reasons (in the first case F[_] is the existential type instead of the higher-kinded one, in the second TypeTag[F] doesn't compile).
I suspect the answer is "it's impossible", but would be very happy if it isn't.
EDIT: we currently use WeakTypeTags as follows (slightly simplified):
trait Element[A] {
val tag: WeakTypeTag[A]
// other irrelevant methods
}
// e.g.
def seqElement[A: Element]: Element[Seq[A]] = new Element[Seq[A]] {
val tag = {
implicit val tA = implicitly[Element[A]].tag
weakTypeTag[Seq[A]]
}
}
trait Container[F[_]] {
def lift[A: Element]: Element[F[A]]
// note that the bound is always satisfied, but we pass the
// tag explicitly when this is used
def tag[A: WeakTypeTag]: WeakTypeTag[F[A]]
}
val seqContainer: Container[Seq] = new Container[Seq] {
def lift[A: Element] = seqElement[A]
}
All of this works fine if we replace WeakTypeTag with TypeTag. Unfortunately, this doesn't:
class Free[F[_]: Container, A: Element]
def freeElement[F[_]: Container, A: Element] {
val tag = {
implicit val tA = implicitly[Element[A]].tag
// we need to get something like TypeTag[F] here
// which could be obtained from the implicit Container[F]
typeTag[Free[F, A]]
}
}
Does this serve your purposes?
def tagHK[F[_], A](implicit tt: TypeTag[HK[F, A]]) = tt
As opposed to using the implicit parameter to get the TypeTag for F and A separately and then composing them, you can directly request the tag you want from the compiler. This passes your test case as desired:
tagHK[Option, Int] == typeTag[HK[Option, Int]] //true
Alternatively, if you have an instance of TypeTag[A] you could try:
object HK {
def apply[F[_]] = new HKTypeProvider[F]
class HKTypeProvider[F[_]] {
def get[A](tt: TypeTag[A])(implicit hktt: TypeTag[HK[F, A]]) = hktt
}
}
Allowing you to do:
val myTT = typeTag[Int]
HK[Option].get(myTT) == typeTag[HK[Option, Int]] //true
Lets say we want to use type classes to implement pretty printing:
trait Printer[T] {def print(t: T)}
with default implementation for ints:
implicit object IntPrinter extends Printer[Int] {
override def print(i : Int): Unit = println(i)
}
Our specific types we want to print are:
trait Foo {
type K
val k: K
}
class IntFoo extends Foo {
override type K = Int
override val k = 123
}
cool. Now I want to build printers for all Foos with printable Ks
implicit def fooPrinter[FP <: Foo](implicit ev: Printer[FP#K]): Printer[FP] =
new Printer[FP] {
override def print(f: FP): Unit = {
Predef.print("Foo: ")
ev.print(f.k)
}
}
lets check that implicits are resolved:
def main(args: Array[String]) {
implicitly[Printer[Int]]
implicitly[Printer[IntFoo]]
}
scalac 2.11.2 says:
diverging implicit expansion for type Sandbox.Printer[Int]
starting with method fooPrinter in object Sandbox
implicitly[Printer[Int]]
whaat?
OK, lets rewrite fooPrinter:
implicit def fooPrinter[KP, FP <: Foo {type K = KP}](implicit ev: Printer[KP]) =
new Printer[FP] {
override def print(f: FP): Unit = {
Predef.print("Foo: ")
ev.print(f.k)
}
}
this works in 2.11, but what's the problem with the first approach?
Unfortunately we're on 2.10, and second solution still doesn't work. It compiles until we add one more sime printer like
implicit object StringPrinter extends Printer[String] {
override def print(s : String): Unit = println(s)
}
and it mysteriously breaks Printer[IntFoo] implicit:
could not find implicit value for parameter e:
Sandbox.Printer[Sandbox.IntFoo]
compiler bugs?
Order of implicit declarations matters. In your source code reorder original code from
implicit object IntPrinter ...
...
implicit def fooPrinter ...
to
implicit def fooPrinter ...
...
implicit object IntPrinter ...