Understanding Mixed Context Bounds of Seq[AnyVal] and Seq[String] - scala

Suppose I have some function that should take a sequence of Ints or a sequence of Strings.
My attempt:
object Example extends App {
import scala.util.Random
val rand: Random.type = scala.util.Random
// raw data
val x = Seq(1, 2, 3, 4, 5).map(e => e + rand.nextDouble())
val y = Seq("chc", "asas")
def f1[T <: AnyVal](seq: Seq[T]) = {
println(seq(0))
}
// this works fine as expected
f1(x)
// how can i combine
f1(y)
}
How can I add this to also work with strings?
If I change the method signature to:
def f1[T <: AnyVal:String](seq: Seq[T])
But this won't work.
Is there a way to impose my required constraint on the types elegantly?

Note the difference between an upper bound
A <: C
and a context bound
A : C
so type parameter clause [T <: AnyVal : String] does not make much sense. Also types such as String are rarely (or never) used as context bounds.
Here is a typeclass approach
trait EitherStringOrAnyVal[T]
object EitherStringOrAnyVal {
implicit val str: EitherStringOrAnyVal[String] = new EitherStringOrAnyVal[String] {}
implicit def aval[T <: AnyVal]: EitherStringOrAnyVal[T] = new EitherStringOrAnyVal[T] {}
}
def f1[T: EitherStringOrAnyVal](seq: Seq[T]): Unit = {
println(seq(0))
}
f1(Seq(1)) // ok
f1(Seq("a")) // ok
f1(Seq(Seq(1))) // nok
or generelized type constraints approach
object Foo {
private def impl[T](seq: Seq[T]): Unit = {
println(seq(0))
}
def f1[T](seq: Seq[T])(implicit ev: T =:= String): Unit = impl(seq)
def f1[T <: AnyVal](seq: Seq[T]): Unit = impl(seq)
}
import Foo._
f1(Seq(1)) // ok
f1(Seq("a")) // ok
f1(Seq(Seq(1))) // nok

I feel like you should write a separate function for both, but there are other ways to do it:
In Dotty, you can just use union types, which is what I'd recommend here:
Edit: As per Alexey Romanov’s suggestion, replaced Seq[AnyVal | String] with Seq[AnyVal | String], which was wrong,
def foo(seq: Seq[AnyVal] | Seq[String]): Unit = {
println(seq)
}
Scastie
If you're not using Dotty, you can still do this in Scala 2 with a couple reusable implicit defs
class Or[A, B]
implicit def orA[A, B](implicit ev: A): Or[A, B] = new Or
implicit def orB[A, B](implicit ev: B): Or[A, B] = new Or
def foo[T](seq: Seq[T])(implicit ev: Or[T <:< AnyVal, T =:= String]): Unit =
println(seq)
foo(Seq("baz", "waldo"))
foo(Seq(23, 34))
foo(Seq(List(), List())) //This last one fails
Scastie
You can also do it with a typeclass, as Luis Miguel Mejía Suárez suggested, but I wouldn't recommend it for such a trivial task since you still have to define 2 functions for each type, along with a trait, 2 implicit objects, and one function that can use instances of that trait. You probably don't want this pattern to handle just 2 different types.
sealed trait DoSomethingToIntOrString[T] {
def doSomething(t: Seq[T]): Unit
}
implicit object DoSomethingToAnyVal extends DoSomethingToAnyValOrString[AnyVal] {
def doSomething(is: Seq[AnyVal]): Unit = println(is)
}
implicit object DoSomethingToString extends DoSomethingToIntOrString[String] {
def doSomething(ss: Seq[String]): Unit = println(ss)
}
def foo[T](t: Seq[T])(implicit dsis: DoSomethingToIntOrString[T]): Unit = {
dsis.doSomething(t)
}
foo(Seq("foo", "bar"))
foo(Seq(1, 2))
In Scastie

def f1( seq: Seq[Any] ): Unit =
println( seq( 0 ) )
This works, because the least common supertype of Int and String (the 'lowest' type that is a supertype of both) would be Any, since Int is a subtype of AnyVal (i.e. 'the primitives) and String is a subtype of AnyRef (i.e. `the heap objects). f1 does not depends in any way on the contents of the list and is not polymorphic in its return type (Unit), so we don't need a type parameter at all.

Related

How to compare types of different, generic HLists?

So I have a user defined input of keys, and the user is also expected to provide serializers for these keys. I am trying to statically ensure that the serializers provided work with the user provided types. Example user usage would be something like:
case class Keys(key1: String, key2: Int)
val keys = Keys("Foo", 2)
val keyDescriptor = (StringSerializer, IntSerializer)
toSerializedKeys(keys, keyDescriptor)
but I would like something like this to fail at compile time:
val keys = Keys("Foo", 2)
val keyDescriptor = (StringSerializer, StringSerializer)
toSerializedKeys(keys, keyDescriptor)
To abstract over arity and attempt to provide compile time type matching on the keys/serializers I'm trying to use shapeless. My current solution works fine given explicit HLists. But as soon as I try to apply this to generic HLists things fall apart.
Current solution:
Assume we have the following user provided serializers:
trait SerializerFn[T] {
def toBytes(t: T): ByteBuffer
}
object StringSerializerFn extends SerializerFn[String] {
override def toBytes(t: String): ByteBuffer = ???
}
object IntSerializerFn extends SerializerFn[Int] {
override def toBytes(t: Int): ByteBuffer = ???
}
I currently create a type class, helper function, and instances to handle serialization of HLists:
trait Serializer[HA <: HList, HB <: HList] {
def toBufs(keys: HA)(fns: HB): List[ByteBuffer]
}
object Serializer extends SerializerInstances {
def toBufs[HA <: HList, HB <: HList](keys: HA)(fns: HB)(
implicit
serializer: Serializer[HA, HB]
): List[ByteBuffer] = {
serializer.toBufs(keys)(fns)
}
}
trait SerializerInstances {
implicit val hnilSerializer: Serializer[HNil, HNil] =
new Serializer[HNil, HNil] {
override def toBufs(keys: HNil)(fns: HNil): List[ByteBuffer] = Nil
}
implicit def hconsSerializer[H, Fn <: SerializerFn[H], TA <: HList, TB <: HList](
implicit
hconsSerializer: Serializer[TA, TB],
): Serializer[H :: TA, Fn :: TB] =
new Serializer[H :: TA, Fn :: TB] {
override def toBufs(keys: H :: TA)(fns: Fn :: TB): List[ByteBuffer] =
List(fns.head.toBytes(keys.head)) ::: hconsSerializer.toBufs(keys.tail)(fns.tail)
}
}
The static type checking I'm going for here is happening in hconsSerializer where we restrict the head of both HLists to be an H and SerializerFn[H], respectively.
And to test it, this compiles fine:
val testKeys = "3" :: "4" :: HNil
val testFns = StringSerializerFn :: StringSerializerFn :: HNil
val testSerializedKeys = Serializer.toBufs(testKeys)(testFns)
and as expected, this doesn't compile:
val testKeys = "3" :: "4" :: HNil
val testFns = StringSerializerFn :: IntSerializerFn :: HNil
val testSerializedKeys = Serializer.toBufs(testKeys)(testFns)
However, when trying to generalize this (so that we can actually use this in a constructor that we provide to users), things fall apart, (I've omitted the Generic conversion from the user provided Product to HList for brevity):
def toSerializedKeys[ReprA <: HList, ReprB <: HList](
keys: ReprA,
fns: ReprB
): List[ByteBuffer] =
Serializer.toBufs(keys)(fns)
For reference, intellij complains that the implicit Serializer can't be found, and explicitly passing hconsSerializer shows:
Required: Serializer[ ReprA, ReprB]
Found: Serializer[Nothing :: HNil, Nothing :: HNil]
and Scalac says:
[error] found : [H, Fn <: com.twitter.beam.io.manhattan.SerializerFn[H], TA <: shapeless.HList, TB <: shapeless.HList]com.twitter.beam.io.manhattan.Serializer[H :: TA,Fn :: TB]
[error] required: com.twitter.beam.io.manhattan.Serializer[ReprA,ReprB]
What kind of implicit evidence do I need to be able to perform this kind of recursive type checking on generic HLists? Is accomplishing something like this even possible? I'm new to Shapeless.
Also, if comparing HList types like this isn't possible. Another solution could be something that allowed the user to define individual implicit key serializers, instead of a full KeyDescriptor that we convert to an HList, e.g something like:
implicit val intSerializer = IntSerializerFn
implicit val strSerizlizer = StringSerializerFn
However, I tried something like this and then tried mapping over the Keys HList with a Poly1 that takes an implicit SerializerFn, but I ran into similar issues when trying to work with a generic HLists.
If you are using Scala3 (aka dotty), here is a simple solution using stdlib only for your purpose:
import scala.deriving.Mirror.ProductOf as PF
import java.nio.ByteBuffer
trait SerializerFn[T]:
def toBytes(t: T): ByteBuffer
object StringSerializerFn extends SerializerFn[String]:
override def toBytes(t: String): ByteBuffer = ???
object IntSerializerFn extends SerializerFn[Int]:
override def toBytes(t: Int): ByteBuffer = ???
case class SI(key1: String, key2: Int)
case class SII(key1: String, key2: Int, key3: Int)
def toSerializedKeys[K <: Product, S <: Tuple](keys: K, sers: S)
(using pf: PF[K], ev: S <:< Tuple.Map[pf.MirroredElemTypes, SerializerFn]): Unit = {}
// success
toSerializedKeys(SI("a", 1), (StringSerializerFn, IntSerializerFn))
toSerializedKeys(SII("a", 1, 2), (StringSerializerFn, IntSerializerFn, IntSerializerFn))
// compile fail
// toSerializedKeys(SI("a", 1), (StringSerializerFn, StringSerializerFn))
// toSerializedKeys(SII("a", 1, 2), (IntSerializerFn, IntSerializerFn, IntSerializerFn))
I guess you just missed evidence serializer: Serializer[ReprA, ReprB] in
def toSerializedKeys[ReprA <: HList, ReprB <: HList](
keys: ReprA,
fns: ReprB
): List[ByteBuffer] =
Serializer.toBufs(keys)(fns)
So just replace this with
def toSerializedKeys[ReprA <: HList, ReprB <: HList](
keys: ReprA,
fns: ReprB
)(implicit serializer: Serializer[ReprA, ReprB]): List[ByteBuffer] =
Serializer.toBufs(keys)(fns)
Then
case class Keys(key1: String, key2: Int)
val keys = Keys("Foo", 2)
val keyDescriptor = (StringSerializer, IntSerializer)
toSerializedKeys(keys, keyDescriptor)
compiles (as expected) and
val keys = Keys("Foo", 2)
val keyDescriptor = (StringSerializer, StringSerializer)
toSerializedKeys(keys, keyDescriptor)
doesn't (as expected).
Just noticed that Alec advised the same in comments.

Achieving Ad hoc polymorphism at function parameter level (mixing parameters of different type)

When I have a function in Scala:
def toString[T: Show](xs: T*): String = paths.map(_.show).mkString
And the following type class instances in scope:
implicit val showA: Show[MyTypeA]
implicit val showB: Show[MyTypeB]
I can use function toString in the following ways:
val a1: MyTypeA
val a2: MyTypeA
val stringA = toString(a1, a2)
val b1: MyTypeB
val b2: MyTypeB
val stringB = toString(b1, b2)
But I cannot call toString mixing parameters of type MyTypeA and MyTypeB:
// doesn't compile, T is inferred to be of type Any
toString(a1, b1)
Is it possible to redefine toString in such a way that it becomes possible to mix parameters of different types (but only for which a Show typeclass is available)?
Note that I am aware of the cats show interpolator which solves this specific example, but I'm looking for a solution which can be applied to different cases as well (e.g. toNumber).
I am also aware of circumventing the problem by calling .show on the parameters before passing them to the toString function, but I'm looking for a way to avoid this as it results in code duplication.
Example with shapeless:
object myToString extends ProductArgs { //ProductArgs allows changing variable number of arguments to HList
//polymorphic function to iterate over values of HList and change to a string using Show instances
object showMapper extends Poly1 {
implicit def caseShow[V](implicit show: Show[V]): Case.Aux[V, String] = {
at[V](v => show.show(v))
}
}
def applyProduct[ARepr <: HList](
l: ARepr
)(
implicit mapper: Mapper[showMapper.type, ARepr]
): String = l.map(showMapper).mkString("", "", "")
}
Now let's test it:
case class Test1(value: String)
case class Test2(value: String)
case class Test3(value: String)
implicit val show1: Show[Test1] = Show.show(_.value)
implicit val show2: Show[Test2] = Show.show(_.value)
println(myToString(Test1("a"), Test2("b"))) //"ab"
println(myToString(Test1("a"), Test2("b"), Test3("c"))) //won't compile since there's no instance of Show for Test3
By the way, I think toString is not the best name, because probably it can cause weird conflicts with toString from java.lang.Object.
If you don't want to mess with shapeless, another solution that comes to my mind is to just create functions with different arity:
def toString[A: Show](a: A): String = ???
def toString[A: Show, B: Show](a: A, b: B): String = ???
//etc
It's definitely cumbersome, but it might be the easiest way to solve your problem.
Here's one way to do it in Dotty (note that most of the Dotty-specific features used here are not necessary; they're just to make life easier, but being able to abstract over tuples of different arities is something you can't do (easily) in Scala 2):
opaque type Show[T] = T => String
opaque type ShowTuple[T <: Tuple] = T => String
object ShowTuple {
given ShowTuple[EmptyTuple] = _ => ""
given showTuple[H, T <: Tuple](using show: Show[H], showTail: ShowTuple[T]) as ShowTuple[H *: T] =
{ case h *: t => show(h) + "," + showTail(t) }
}
def multiToString[T <: Tuple](t: T)(using showTuple: ShowTuple[T]) =
showTuple(t)
It can be used like this:
class TypeA(val i: Int)
class TypeB(val s: String)
class TypeC(val b: Boolean)
given Show[TypeA] = t => s"TypeA(${t.i})"
given Show[TypeB] = t => s"TypeB(${t.s})"
given Show[TypeC] = t => s"TypeC(${t.b})"
println(multiToString((new TypeA(10), new TypeB("foo"), new TypeC(true))))
Using a type for which an implicit is not given fails:
class TypeD
multiToString((new TypeA(10), new TypeB("foo"), new TypeC(true), new TypeD))
Try it in Scastie
What is the type of paths?
If it's List[T] then there should be an implicit Show[T] in scope.
If it's List[Any] then there should be an implicit Show[Any] in scope.
If paths contains elements of different types and paths is not a List[Any] then paths shouldn't be a List[...] at all. It can be of type L <: HList. You can try
import shapeless.{HList, HNil, Poly1, Poly2}
import shapeless.ops.hlist.{LeftReducer, Mapper}
trait Show[T] {
def show(t: T): String
}
implicit class ShowOps[T](t: T) {
def show(implicit s: Show[T]): String = s.show(t)
}
object show extends Poly1 {
implicit def cse[T: Show]: Case.Aux[T, String] = at(_.show)
}
object concat extends Poly2 {
implicit def cse: Case.Aux[String, String, String] = at(_ + _)
}
def toString[L <: HList, L1 <: HList](xs: L)(implicit
mapper: Mapper.Aux[show.type, L, L1],
reducer: LeftReducer.Aux[L1, concat.type, String]
): String = xs.map(show).reduceLeft(concat)
type MyTypeA
type MyTypeB
implicit val showA: Show[MyTypeA] = ???
implicit val showB: Show[MyTypeB] = ???
val a1: MyTypeA = ???
val b1: MyTypeB = ???
toString(a1 :: b1 :: HNil)

Scala: upper bound [T <: AnyRef] does not allow to return [AnyRef]

I'm trying to express the following idea:
Function caseClassFields should return an array of (String, T) pairs, by processing a case class.
I put upper bound for T, expecting that it should be a subtype of AnyRef or AnyRef itself.
Here is a function:
def caseClassFields[T <: AnyRef](obj: AnyRef): Array[(String, T)] = {
val metaClass = obj.getClass
metaClass.getDeclaredFields.map {
field => {
field.setAccessible(true)
(field.getName, field.get(obj))
}
}
}
But unfortunately I get following error:
Expression of type Array[(String, AnyRef)] doesn't conform to expected type Array[(String, T)]
How to fix this?
Doing what you want with reflection and keeping type safety are orthogonal requirements. But shapeless, a library for generic derivation, can do what you want and still keep you type safe.
Here's a short example using shapeless to get you started.
We first define our algebra:
sealed trait ValidatableField
case class ValidatableString(value: Boolean)
extends ValidatableField
case class ValidatableInt(value: Boolean) extends ValidatableField
case class ValidatableRecord(fields: List[(String, ValidatableField)])
extends ValidatableField
Now we define our validator trait:
trait Validator[T] {
def validate(value: T): ValidatableField
}
trait RecordValidator[T] extends Validator[T] {
def validate(value: T): ValidatableRecord
}
Now lets define, for the sake of the example, validation on Int and String:
implicit val intValidator = new Validator[Int] {
override def validate(t: Int): ValidatableField = ValidatableInt(t > 42)
}
implicit val stringValidator = new Validator[String] {
override def validate(t: String): ValidatableField = ValidatableString(t.length < 42)
}
Now we define a generic implementation for HList which will cover our ValidatableRecord which is the generic representation of our case class:
implicit val hnilEncoder: RecordValidator[HNil] = new RecordValidator[HNil] {
override def validate(value: HNil): ValidatableRecord = ValidatableRecord(Nil)
}
implicit def hlistValidator[K <: Symbol, H, T <: HList](
implicit witness: Witness.Aux[K],
hEncoder: Lazy[Validator[H]],
tEncoder: RecordValidator[T]
): RecordValidator[FieldType[K, H] :: T] = {
val fieldName = witness.value.name
new RecordValidator[::[FieldType[K, H], T]] {
override def validate(value: ::[FieldType[K, H], T]): ValidatableRecord = {
val head = hEncoder.value.validate(value.head)
val tail = tEncoder.validate(value.tail)
ValidatableRecord((fieldName, head) :: tail.fields)
}
}
}
implicit def genericEncoder[A, H <: HList](
implicit generic: LabelledGeneric.Aux[A, H],
hEncoder: Lazy[RecordValidator[H]]): Validator[A] = {
new RecordValidator[A] {
override def validate(value: A): ValidatableRecord =
hEncoder.value.validate(generic.to(value))
}
}
With this much code, we can now validate any case class which has a String and Int field in it, and it is trivial to add other validator for more primitives:
object Test {
def main(args: Array[String]): Unit = {
case class Foo(s: String, i: Int)
val foo = Foo("hello!", 42)
println(Validator[Foo].validate(foo))
}
}
Yields:
ValidatableRecord(List((s,ValidatableString(true)), (i,ValidatableInt(false))))
I know this can be overwhelming a bit, but David Gurnells "Guide To Shapeless" is a great place to get started.
The reason is field.get(obj) returns AnyRef while your return type is T. Therefore, you need to convert it into T. However, I don't see any use of Generic type T in your code, so you can simply change the return type to Array[(String, AnyRef)].
def caseClassFields[T <: AnyRef](obj: AnyRef): Array[(String, AnyRef)]
However, if you insist to use Generic, you need to convert field.get(obj) to type T. Note, that you might get exception in case of invalid type while converting to type T.
def caseClassFields[T <: AnyRef](obj: AnyRef): Array[(String, T)] = {
val metaClass = obj.getClass
metaClass.getDeclaredFields.map {
field => {
field.setAccessible(true)
(field.getName, field.get(obj).asInstanceOf[T])
}
}
}
case class Foo(name:String)
val result:Array[(String, String)] = caseClassFields[String](Foo("bar"))
As discussed in the comments you probably want to use shapeless, but to elaborate.
The method field.get() isnt related to the type parameter. Normally you would use a type parameter like this
def caseClassFields[T <: AnyRef](obj: T): Array[(String, T)] = ???
or this ..
def caseClassFields[T <: AnyRef](obj: Container[T]): Array[(String, T)] = ???
If there was some link between field.get and T it could work, but the relationship would need to be proven to the compiler. As the T can be anything the compiler cant prove anything about it.
I can strongly recommend this book the 'Type Astronaut’s Guide to Shapeless' as a intro to the topic.
http://underscore.io/books/shapeless-guide/
https://github.com/milessabin/shapeless

Resolve implicit parameter from super type

Is it possible to resolve an implicit parameter for a type B if an implicit is defined for its super type A?
Here is an example :
I have an Enumerable typeclass :
trait Enumerable[A] {
def name(a: A): String
def list: List[A]
//... other methods
}
object Enumeration {
def name[A, T >: A](a: A)(implicit ev: Enumerable[T]) = ev.name(a)
def list[T](implicit ev: Enumerable[T]) = ev.list
// ...
}
Then I define an instance of enumerable :
sealed trait Season
case object Winter extends Season
case object Spring extends Season
case object Summer extends Season
case object Fall extends Season
implicit val seasonEnumerable = new Enumerable[Season] {
override def list: List[Season] = List(Winter, Spring, Summer, Fall)
}
// working :
Enumeration.name(Winter: Season) shouldBe "winter"
// faling :
Enumeration.name(Winter) shouldBe "winter"
Enumeration.name(Winter) is failing if I don't tell scalac that Winter is a Season. I've specified that the implicit parameter in the 'name' method signature is a supertype of A, but it's not sufficient...
Is there a better way to do this?
Eduardo's answer explains why the version with [A, T >: A] doesn't work. But there is a simpler solution to the problem than he gives: instead of introducing T infer as a type parameter, introduce it by an existential type:
def name[A](a: A)(implicit ev: Enumerable[T >: A] forSome { type T }) = ev.name(a)
Or, using a shorthand,
def name[A](a: A)(implicit ev: Enumerable[_ >: A]) = ev.name(a)
Then the compiler only has to decide what T is when looking for ev.
This is a common inconvenience whenever you need type-dependent types to be inferred. Your method
def name[A, T >: A](a: A)(implicit ev: Enumerable[T])
when called on Winter, first A will be inferred to Winter.type and then T to be A, as it conforms to that bound and there are no more constraints on it at that point. Then of course the compiler won't find an instance of Enumerable[Winter.type].
There's an easy solution with type members though:
trait AnyEnumerable {
type E
def name[A <: E](a: A): String
def list: List[E]
}
object Enumeration {
def name[A](a: A)(implicit ev: AnyEnumerable { type E >: A }) = ev.name(a)
def list[T](implicit ev: AnyEnumerable { type E = T }) = ev.list
// ...
}
// an implicit for `Season`
implicit val seasonEnumerable: AnyEnumerable { type E = Season } =
new AnyEnumerable {
type E = Season
def name[A <: Season](a: A): String = a.toString
def list: List[Season] = List(Winter, Spring, Summer, Fall)
}
// compiles!
val zzz = Enumeration.name(Winter)

scala bind type parameter of trait with type parameter of function

It is difficult to explain problem using few words, so I prepared pice of code to present issue.
Let's develop container of type Container[T1,T2] and implicits for wrapping any value in that container. If the value is type of Container[T1,T2] wrapping should return the same type. More over wrapping method should taking parameter of type T1 (the same as in container), and resulting with container with replaced T1 value.
Solution must conform generics and implicits manner.
Sounds little confusing, let's read the code :)
Container:
case class Container[T1, T2](t1: T1, t2: T2)
Trait with wrapping method:
trait ToContainer[A] {
def wrappingMethod[E](e: E): Container[E, A]
}
Object with implicits:
object ToContainers {
import language.implicitConversions
implicit def implicitMethod[A](a: => A) = new ToContainer[A] {
def wrappingMethod[E](e: E): Container[E, A] = Container(e, a)
}
implicit def implicitMethod2[E, A] (c: => Container[E, A])(implicit d:DummyImplicit): ToContainer[A] = new ToContainer[A] {
def wrappingMethod[EX](e: EX): Container[EX, A] = c.copy(e)
}
}
So that was the code.
The problem is that I need somehow bind type parameter EX of function def wrappingMethod[EX] to the parameter E of def implicitMethod2[E, A].
After this something like this should work (and works):
scala> import ToContainers._
import ToContainers._
scala> val c1: Container[String, Int] = 1234.wrappingMethod("abc")
c1: Container[String,Int] = Container(abc,1234)
scala> val c2: Container[String, Int] = c1.wrappingMethod("XXX")
c2: Container[String,Int] = Container(XXX,1234)
... but this must yield compilation error, and don't :(
(Take a look on types: c1 has [String, Int] and c3 has [Int,Int]. I want to prevent this.)
scala> val c3 = c1.wrappingMethod(0)
c3: Container[Int,Int] = Container(0,1234)
Any ideas great appreciated :)
BTW: I am using this version of scala:
Welcome to Scala version 2.10.0-M7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_07)
EDITED:
I've fiexed errors. Code is working now.
The sample code you provided does not work, so it's a bit difficult to provide a good answer. However, can't you just do something like:
implicit def implicitMethod2[E, A] (c: => Container[E, A])(implicit d:DummyImplicit): ToContainer[A] = new ToContainer[A] {
def wrappingMethod[E](e: E): Container[EX, A] = c.copy(e)
}
So simply replace the EX type parameter with E.
You need to move the type parameter E up to ToContainer:
trait ToContainer[E, A]
def wrappingMethod(e: E): Container[E, A]
}
object ToContainers {
import language.implicitConversions
implicit def implicitMethod[E, A](a: => A) = new ToContainer[E, A] {
def wrappingMethod(e: E): Container[E, A] = Container(e, a)
}
implicit def implicitMethod2[E, A] (c: => Container[E, A])(implicit d:DummyImplicit): ToContainer[E, A] = new ToContainer[E, A] {
def wrappingMethod(e: E): Container[E, A] = c.copy(e)
}
}