:43)
```
---
### Work around the contravariance issue?
Update `familyShow` to directly call the instances `member{1,2}Show` without implicit resolution:
```scala
given familyShow: Show[Family] = Show[Family] {
case Member1 => s"Family(${member1Show(Member1)})"
case m: Member2 => s"Family(${member2Show(m)})"
}
```
---
… still not sufficient:
```scala
scala> summon[Show[Member2]].apply(Member2("foo"))
res: String = Family(Member2(foo))
// ... not “Member2(foo)” from member2Show ⬅️
```
… still resolve `familyShow` instead of more specific instance (there `member2Show`);
Could be ok, except if we want `x: Member2` (explicitly known a `Member2`) to be encoded with specific `Show`, different from when the same `x` is just known as a `Family` instance.
---
### Better implicit parameters?
With `Show` instances for subtypes resolved as implicit parameters, rather than using `summon`.
```scala
given familyShow(using _1: Show[Member1.type], // ⬅️
_2: Show[Member2]): Show[Family] = Show[Family] {
case Member1 => _1.apply(Member1)
case m: Member2 => _2.apply(m)
}
```
---
This time, the specific instance is resolved,
```scala
scala> summon[Show[Member2]].apply(Member2("foo"))
res: String = Member2(foo)
```
but …
---
… now it’s weird for the parent type `Family`:
```scala
scala> summon[Show[Family]].apply(Member2("foo"))
res: String = Member2(foo)
// ... not Family(Member2(foo)) ⬅️
```
---
### Implicit objects
Let's try to define `Show` instances as objects:
```scala
implicit object Member1Show extends Show[Member1.type] {
def apply(m: Member1.type): String = "Member1"
}
implicit object Member2Show extends Show[Member2] {
def apply(m: Member2): String = s"Member2(${m.v})"
}
given familyShow: Show[Family] = Show[Family] {
case Member1 => s"Family(${Member1Show(Member1)})"
case m: Member2 => s"Family(${Member2Show(m)})"
}
```
---
… raise ambiguity issue for implicit resolution
```scala
scala> summon[Show[Member2]]
-- [E172] Type Error: ----------------------------------
1 |summon[Show[Member2]]
| ^
|Ambiguous given instances: both object Member2Show and given instance
familyShow match type Show[Member2] of parameter x
of method summon in object Predef
1 error found
```
---
### Revert to invariant `Show`
```scala
trait Show[T] {
def apply(value: T): String
}
```
Then *everything is ok* for sealed family …
```scala
scala> summon[Show[Member2]].apply(Member2("foo"))
res: String = Member2(foo)
scala> summon[Show[Family]].apply(Member2("foo"))
res: String = Family(Member2(foo))
```
---
… but come back to [issue for `iterableShow`](#show-any-iterable):
```scala
scala> summon[Show[List[String]]]
-- [E172] Type Error: ----------------------------
1 |summon[Show[List[String]]]
| ^
|No given instance of type Show[List[String]]
was found for parameter x of method summon in object Predef
1 error found
```
---
### Try generic type constraints for `iterableShow`
Define a Show instance of any `T <: Iterable[_]`:
```scala
given iterableShow[A, T <: Iterable[_]](using w: Show[A]): Show[T] = ???
```
---
… but it doesn’t help the implicit resolution:
```scala
scala> summon[Show[List[String]]]
-- [E172] Type Error: -----------------------------------
1 |summon[Show[List[String]]]
| ^
|No best given instance of type Show[List[String]] was found
...
```

---
### Higher kinds to the rescue
Specify a `Show` instance of any `Iterable M` whose *type constructor* accept one *type parameter*:
```scala
import scala.language.higherKinds
given iterableShow[A, M[_] <: Iterable[_]/* ⬅️ */](
using s: Show[A]): Show[M[A]] = sys.error("resolved")
```
… now the resolution seems ok:
```scala
scala> summon[Show[List[String]]]
java.lang.RuntimeException: resolved
```
---
### First implementation with higher kinds
For now `iterableShow` is resolvable but not implemented, let’s give it a first try:
```scala
given iterableShow[A, M[_] <: Iterable[_]](
using w: Show[A]): Show[M[A]] =
Show[M[A]] { (as: M[A]) =>
as.map { (a: A) =>
w(a)
}.mkString
}
```
---
… but it fails to compile:
```scala
-- [E007] Type Mismatch Error: ----------------
4 | as.map { (a: A) =>
| ^
| Found: A => String
| Required: Any => String
...
```
---
Different meaning of `_` in type expression `M[_] <: Iterable[_]`,
- in `M[_]` : type constructor with one unnamed type parameter,
- in `Iterable[_]` : similar to `Iterable[Any]`
(like `?` in Java generics, doesn't require `scala.language.higherKinds`)
---
... it lacks of evidence that `_` in `Iterable[_]` can be `A` when using applying `M[A]`.

---
### Fix high kinds implementations
Specify it with `M[T] <: Iterable[T]` to guarantee that with `M[A]` the `Iterable` operations are parameterized with the “same” `A`.
```scala
given iterableShow[A, M[T] <: Iterable[T]](
using w: Show[A]): Show[M[A]] = Show[M[A]] { as =>
as.map { (a: A) =>
w(a)
}.mkString
}
```
… it compiles, let’s test it ... 🙏
---
### Test the high kinds implementation
First the newly implemented `iterableShow`,
```scala
scala> summon[Show[List[String]]].apply(List("foo"))
res: String = foo
scala> summon[Show[Set[String]]].apply(Set("bar"))
res: String = bar
```
… then check there is no regression for the sealed family:
```scala
scala> summon[Show[Member2]].apply(Member2("foo"))
res: String = Member2(foo)
scala> summon[Show[Family]].apply(Member2("foo"))
res: String = Family(Member2(foo))
```
---
### Finally everything is ok

---
## Some usefuls readings
*See [typeclass slides](../scala2-typeclass/) for Scala 2*
- [Be friend with covariance and contravariance](http://julien.richard-foy.fr/blog/2013/02/21/be-friend-with-covariance-and-contravariance/); Julien Richard-Foy (21/2/2013)
- [SI-2509](https://issues.scala-lang.org/browse/SI-2509): Contravariance mucks with implicit resolution;
Created on issue.scala-lang.org 10/2009, updated 8/2016; Open/unresolved
- [End the blight of contravariance](https://groups.google.com/forum/#!topic/scala-language/ZE83TvSWpT4); Scala-language Google group (5/2012)
- [Implicit Resolution with Contravariance](https://stackoverflow.com/a/21921296); StackOverflow (2/2014)
- The [Play-JSON Pull Request](https://github.com/playframework/play-json/pull/216/) that has inspired those slides