0

In my understanding the following two functions and their calls should be identical:

def f1[L1 <: HList, L2](xs: L1)(implicit sequencer: Sequencer.Aux[L1, Option, L2]) {
  println(xs.sequence)
}

def f2[L1 <: HList : Sequencer.Aux[*, Option, L2], L2](xs: L1) {
  println(xs.sequence)
}

f1[Option[Int] :: Option[String] :: HNil, Int :: String :: HNil](Some(42) :: Some("foo") :: HNil)
f2[Option[Int] :: Option[String] :: HNil, Int :: String :: HNil](Some(42) :: Some("foo") :: HNil)

However, the call to f2 doesn't compile:

could not find implicit value for evidence parameter of type cats.sequence.Sequencer[Option[Int] :: Option[String] :: shapeless.HNil]{type F[X] = Option[X]; type LOut = Int :: String :: shapeless.HNil}

The Scala compile seems to expand the type alias Sequencer.Aux in the second case and isn't able to construct a suitable implicit.

If I directly define my function with the expanded type, no implicit can be constructed either:

def f3[L1 <: HList, L2](xs: L1)(implicit sequencer: Sequencer[L1]{type F[X] = Option[X]; type LOut = L2}) {
  println(xs.sequence)
}

Apart from the inconvenience of not being able to use the more compact context bound syntax there are two things that I don't understand about this situation:

  1. why is the type of the evidence implicit only expanded if i use the context bound syntax? (and are there more semantical differences between the two syntaxes?)
  2. why is Scala unable to construct a suitable implicit for the expanded case? After all, Sequencer.Aux is only a type alias defined like this:
type Aux[L <: HList, F0[_], LOut0] = Sequencer[L] {
  type F[X] = F0[X]
  type LOut = LOut0
}

I would have expected both types to behave identical.

mrArkwright
  • 254
  • 2
  • 10

1 Answers1

0

Looks like a bug. Bugs should be reported here: https://github.com/scala/bug/issues

I tried to create minimal example.

And maybe I oversimplified the example but now I have issues even with HNil case.

For

import cats.Applicative
import shapeless.{::, HList, HNil}
import cats.instances.option._

trait Sequencer[L <: HList] extends Serializable {
  type F[_]
}

object Sequencer {
  type Aux[L <: HList, F0[_]] = Sequencer[L] {
    type F[X] = F0[X]
  }

  implicit def nil[F0[_]](
    implicit F: Applicative[F0]
  ): Aux[HNil, F0] = null
}

implicitly[Sequencer.Aux[HNil, Option]] compiles but implicitly[Sequencer[HNil]{type F[X] = Option[X]}] doesn't and there is warning (scalacOptions += "-Xlog-implicits")

//Information: App.this.Sequencer.nil is not a valid implicit value for App.Sequencer[shapeless.HNil]{type F[X] = Option[X]} because:
//hasMatchingSymbol reported error: could not find implicit value for parameter F: cats.Applicative[Option[X]]

And probably here we can see the reason: could not find implicit value for parameter F: cats.Applicative[Option[X]] should be could not find implicit value for parameter F: cats.Applicative[Option].

But for some reason if I remove implicit F: Applicative[F0] then for

import shapeless.{::, HList, HNil}

trait Sequencer[L <: HList] extends Serializable {
  type F[_]
}

object Sequencer {
  type Aux[L <: HList, F0[_]] = Sequencer[L] {
    type F[X] = F0[X]
  }

  implicit def nil[F0[_]](): Aux[HNil, F0] = null
}

implicitly[Sequencer.Aux[HNil, Option]] doesn't compile although implicitly[Sequencer.Aux[HNil, Option]](Sequencer.nil()) compiles.

implicitly[Sequencer[HNil]{type F[X] = Option[X]}] doesn't compile either. And if we write implicitly[Sequencer[HNil]{type F[X] = Option[X]}](Sequencer.nil()) we'll see why

//Error: inferred kinds of the type arguments (Option[X]) do not conform to the expected kinds of the type parameters (type F0).
//Option[X]'s type parameters do not match type F0's expected parameters:
//class Option has one type parameter, but type F0 has one

... has one type parameter, but ... has one shows that this is a bug.

Bug tracker shows open issues for "implicit" and "higher-kind"

https://github.com/scala/bug/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+implicit+higher-kind

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • 1
    I have no problems compiling all of these implicitly expressions. No compiler errors or warnings at all. I'm using Scala 2.13.1, Cats 2.0.0 and Shapeless 2.3.3. – mrArkwright Nov 06 '19 at 12:17