I am trying to create a hlist implicitly.
case class A(value: Int)
implicit def lift(single: A): A :: HNil = single :: HNil
def something[L <: HList](l: L)(implicit lUBConstraint: LUBConstraint[L, A],
isHCons: IsHCons[L]) = {
println("works")
}
something(A(1) :: A(2) :: HNil) //works
something(A(1)) //not works
something(lift(A(1))) //works
something(A(1)) is not working. However, I use intellij idea and It can detect that lift is proper to use here.
Here is the error message from compiler.
inferred type arguments [Boot.A] do not conform to method something's type parameter bounds [L <: shapeless.HList]
[error] something(A(1)) //not works [error] ^ [error]
type mismatch; [error] found : Boot.A [error] required: L [error] something(A(1))
could not find implicit value for parameter lUBConstraint: shapeless.LUBConstraint[L, Boot.A] [error] something(A(1)
IIRC Scala implicit conversions don't trigger to satisfy type bounds.
You can modify your definition of something to allow any such conversions to work:
def something[X, L <: HList](x: X)(
implicit asHList: X => L,
lUBConstraint: LUBConstraint[L, A],
isHCons: IsHCons[L]
) = {
println("works")
}
For single argument, this will use your lift function, and <:< from Predef for actual HLists
Related
Any idea why this fails to find the implicit view?
// Making B invariant fixes it.
sealed trait ImplicitlyStable[A, +B]
object ImplicitlyStable {
implicit def convertibleToStable[A, B](implicit
aToB: A => B,
// Removing bToB fixes it.
bToB: ImplicitlyStable[B, B]
): ImplicitlyStable[A, B] = ???
}
object Test {
def testConvertibleToStable[A, B](implicit
aToB: A => B,
bToB: ImplicitlyStable[B, B]
): ImplicitlyStable[A, B] =
implicitly[ImplicitlyStable[A, B]]
}
It fails with:
[error] !I e: ImplicitlyStable[A, B]
[error] ImplicitlyStable.convertibleToStable invalid because
[error] !I aToB: A => B
[error] No implicit view available from A => B.
[error]
[error] implicitly[ImplicitlyStable[A, B]]
[error] ^
[error] one error found
It says No implicit view available from A => B which is clearly not true as there is an implicit parameter of that type.
Is this one of those situations where it is inferring Nothing for B? If so, why would it do that?
If I add:
private def unexpected: Nothing = sys.error("Unexpected invocation")
implicit def nothingStableAmbig1[A]: ImplicitlyStable[Nothing, A] = unexpected
implicit def nothingStableAmbig2[A]: ImplicitlyStable[Nothing, A] = unexpected
implicit def nothingStableAmbig3[A]: ImplicitlyStable[A, Nothing] = unexpected
implicit def nothingStableAmbig4[A]: ImplicitlyStable[A, Nothing] = unexpected
Then it fails with:
[error] ambiguous implicit values:
[error] both method nothingStableAmbig3 in object ImplicitlyStable of type [A]ImplicitlyStable[A,Nothing]
[error] and method nothingStableAmbig4 in object ImplicitlyStable of type [A]ImplicitlyStable[A,Nothing]
[error] match expected type ImplicitlyStable[A,B]
[error] implicitly[ImplicitlyStable[A, B]]
[error] ^
So sure enough, it is inferring Nothing, but why?
It seems like this might be a bug in Scala 2 that has been fixed in Scala 3.
I raised an issue for it.
I'm not sure if there is any more reasoning behind why it is inferring Nothing. If anyone knows then that would be great.
import shapeless._; import labelled._;
object CreateField {
type OptionalField[K <: Symbol, T] = FieldType[K, Option[T]]
def pure[K <: Symbol, T](key: Witness.Aux[K], v: Option[T]): OptionalField[K, T] = {
field[K](v)
}
}
The complain was
found : v.type (with underlying type Option[T]) [error] required:
shapeless.labelled.KeyTag[K,Option[T]] with Option[T]
However, if you specify the type for field[K].apply[Option[T]] it compiles, or if you simply first set it to a val and return that val, that is the following method body compiles:
def pure[K <: Symbol, T](key: Witness.Aux[K], v: Option[T]): OptionalField[K, T] = {
val f = field[K](v)
f
}
}
If you don't use the OptionalField type alias, it also compiles.
Is this a ScalaC bug or it's just the way scalaC infers type is somehow incompatible with this field method from shapeless?
On Scala 2.10.4, given the following trait and case classes:
scala> trait Parent
defined trait Parent
scala> case class Girl() extends Parent
defined class Girl
scala> case class Boy() extends Parent
defined class Boy
I'm trying to define a method, f, that produces a Set[Class[A]] where A's type is A <: Parent.
scala> def f[A <: Parent]: Set[Class[A]] = Set[Class[A]](classOf[Boy], classOf[Girl])
<console>:12: error: type mismatch;
found : Class[Boy](classOf[$Boy])
required: Class[A]
def f[A <: Parent]: Set[Class[A]] = Set[Class[A]](classOf[Boy], classOf[Girl])
^
<console>:12: error: type mismatch;
found : Class[Girl](classOf[$Girl])
required: Class[A]
def f[A <: Parent]: Set[Class[A]] = Set[Class[A]](classOf[Boy], classOf[Girl])
But, I can make it work if I use, what I believe is the "wildcard":
scala> def g[A <: Parent]: Set[Class[_]] = Set[Class[_]](classOf[Boy], classOf[Girl])
g: [A <: Parent]=> Set[Class[_]]
And it works:
scala> g
res5: Set[Class[_]] = Set(class Boy, class Girl)
Why did the first approach fail, but the second succeeded? Lastly, is there any risk (to type safety) using Class[_] in the above definition of g?
The problem is that Class[A] is invariant in its type parameter. So Class[Boy] is not a Class[Parent]. The compiler will warn you of this if you set an explicit return type of Set[Class[Parent]].
scala> def f[_ <: Parent]: Set[Class[Parent]] = Set(classOf[Boy], classOf[Girl])
<console>:24: error: type mismatch;
found : Class[Boy](classOf[$Boy])
required: Class[Parent]
Note: Boy <: Parent, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Parent`. (SLS 3.2.10)
def f[_ <: Parent]: Set[Class[Parent]] = Set(classOf[Boy], classOf[Girl])
The following method uses existential types, which essentially means you don't care what the type is. _ is a completely unbound, and the type parameter A is superfluous.
def g[A <: Parent]: Set[Class[_]] = Set[Class[_]](classOf[Boy], classOf[Girl])
You might as well write:
def g: Set[Class[_]] = Set[Class[_]](classOf[Boy], classOf[Girl])
Lastly, is there any risk (to type safety) using Class[_] in the above definition of g?
Type safety has pretty much gone out the window at this point, because _ can be anything. Boy, Girl, Parent, Any, Toaster, ...
I think the best you can hope for is to heed the warning and get something like this:
def g: Set[Class[_ <: Parent]] = Set(classOf[Boy], classOf[Girl])
This will at least ensure that you have a Set with elements bounded above by Parent. Exactly what you intend to do with it, I don't know.
Suppose I've got a type class that proves that all the types in a Shapeless coproduct are singleton types:
import shapeless._
trait AllSingletons[A, C <: Coproduct] {
def values: List[A]
}
object AllSingletons {
implicit def cnilSingletons[A]: AllSingletons[A, CNil] =
new AllSingletons[A, CNil] {
def values = Nil
}
implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit
tsc: AllSingletons[A, T],
witness: Witness.Aux[H]
): AllSingletons[A, H :+: T] =
new AllSingletons[A, H :+: T] {
def values = witness.value :: tsc.values
}
}
We can show that it works with a simple ADT:
sealed trait Foo
case object Bar extends Foo
case object Baz extends Foo
And then:
scala> implicitly[AllSingletons[Foo, Bar.type :+: Baz.type :+: CNil]].values
res0: List[Foo] = List(Bar, Baz)
Now we want to combine this with Shapeless's Generic mechanism that'll give us a coproduct representation of our ADT:
trait EnumerableAdt[A] {
def values: Set[A]
}
object EnumerableAdt {
implicit def fromAllSingletons[A, C <: Coproduct](implicit
gen: Generic.Aux[A, C],
singletons: AllSingletons[A, C]
): EnumerableAdt[A] =
new EnumerableAdt[A] {
def values = singletons.values.toSet
}
}
I'd expect implicitly[EnumerableAdt[Foo]] to work, but it doesn't. We can use -Xlog-implicits to get some information about why:
<console>:17: shapeless.this.Witness.apply is not a valid implicit value for
shapeless.Witness.Aux[Baz.type] because:
Type argument Baz.type is not a singleton type
implicitly[EnumerableAdt[Foo]]
^
<console>:17: this.AllSingletons.coproductSingletons is not a valid implicit
value for AllSingletons[Foo,shapeless.:+:[Baz.type,shapeless.CNil]] because:
hasMatchingSymbol reported error: could not find implicit value for parameter
witness: shapeless.Witness.Aux[Baz.type]
implicitly[EnumerableAdt[Foo]]
^
<console>:17: this.AllSingletons.coproductSingletons is not a valid implicit
value for AllSingletons[Foo,this.Repr] because:
hasMatchingSymbol reported error: could not find implicit value for parameter
tsc: AllSingletons[Foo,shapeless.:+:[Baz.type,shapeless.CNil]]
implicitly[EnumerableAdt[Foo]]
^
<console>:17: this.EnumerableAdt.fromAllSingletons is not a valid implicit
value for EnumerableAdt[Foo] because:
hasMatchingSymbol reported error: could not find implicit value for parameter
singletons: AllSingletons[Foo,C]
implicitly[EnumerableAdt[Foo]]
^
<console>:17: error: could not find implicit value for parameter e:
EnumerableAdt[Foo]
implicitly[EnumerableAdt[Foo]]
^
Baz.type obviously is a singleton type, though. We can try putting the Witness instances in scope manually just for fun:
implicit val barSingleton = Witness[Bar.type]
implicit val bazSingleton = Witness[Baz.type]
And somehow now it works:
scala> implicitly[EnumerableAdt[Foo]].values
res1: Set[Foo] = Set(Bar, Baz)
I don't understand why these instances would work in this context while the ones generated by the Witness.apply macro method (which we used to create them) don't. What's going on here? Is there a convenient workaround that doesn't require us to enumerate the constructors manually?
This works as written as of the most recent shapeless 2.1.0-SNAPSHOT.
Can someone explain why the following doesn't compile? I want that BB[A] is also a List[A]. The method body only enforces this view.
scala> def x[A, BB[_] <: List[_]](p: BB[A]) {p: List[A]}
<console>:8: error: type mismatch;
found : BB[A]
required: List[A]
def x[A, BB[_] <: List[_]](p: BB[A]) {p: List[A]}
^
I think you need to name the _ parameter.
scala> def x[A, BB[X] <: List[X]](p: BB[A]) {p: List[A]}
works.