7

In Scala 3 summon seems to do the same thing as the old implicitly. But when we dig into actual examples we see that isn't the case. For example

case class A(i: Int, s: String)

val mirror    = implicitly[Mirror.Of[A]]    
type ValueOfs = Tuple.Map[mirror.MirroredElemLabels, ValueOf]
val valueOfs  = summonAll[ValueOfs]

def values(t: Tuple): Tuple = t match
  case (h: ValueOf[_]) *: t1 => h.value *: values(t1)
  case EmptyTuple => EmptyTuple

produces the error

cannot reduce inline match with  
 scrutinee:  compiletime.erasedValue[App.ValueOfs] : App.ValueOfs  
 patterns :  case _:EmptyTuple  
             case _:*:[t @ _, ts @ _]

However replacing implicitly[Mirror.Of[A]] with summon[Mirror.Of[A]] compiles fine.

What are the subtleties of summon vs implicitly in this case and in general?

kag0
  • 5,624
  • 7
  • 34
  • 67
  • [This answer](https://stackoverflow.com/a/67143077/2288659) may be related. Though I don't know enough about Scala 3's `Mirror` type to be able to coherently relate that to your code snippet, so I'll let someone else do the honors. – Silvio Mayolo Jul 14 '21 at 01:18
  • `summon` is similar to `shapeless.the` https://typelevel.org/blog/2014/01/18/implicitly_existential.html https://stackoverflow.com/questions/65634897/in-scala-2-13-why-is-it-sometimes-impossible-to-summon-type-class-explicitly https://stackoverflow.com/questions/65062041/behaviour-of-context-bounds-and-implicit-parameter-lists-with-regards-to-path-de https://stackoverflow.com/questions/64438704/implementing-a-typeclass-using-type-parameters-versus-abstract-types – Dmytro Mitin Jul 14 '21 at 14:49

1 Answers1

4

Given

case class A(i: Int, s: String)

we can see that summon and implicitly return the same runtime value

assert(implicitly[Mirror.Of[A]] eq summon[Mirror.Of[A]])

but they have different compile time types

def fun[A,B]( a: A, b: B )( implicit ev: A =:= B ) = ???
fun(implicitly[Mirror.Of[A]], summon[Mirror.Of[A]])
    Cannot prove that deriving.Mirror.Of[Worksheet.A] =:= (
      deriving.Mirror{
        MirroredType = Worksheet.A; MirroredMonoType = Worksheet.A; 
          MirroredElemTypes <: Tuple
      }
     & 
      scala.deriving.Mirror.Product{
        MirroredMonoType = Worksheet.A; MirroredType = Worksheet.A; 
          MirroredLabel = ("A" : String)
      }
    ){
      MirroredElemTypes = (Int, String); 
        MirroredElemLabels = (("i" : String), ("s" : String))
    }.

The one returned by summon is more specific, although I'm not sure how/why this applies to the case in the question.

kag0
  • 5,624
  • 7
  • 34
  • 67