Reputation: 1782
With the following code snippet I cannot figure out why the final value result
is of type Any
:
object reporter extends Poly1 {
implicit def wrap[T, F <% (Function1[String, T], Nat)] = at[F] { fn =>
val f = fn._1
val n = fn._2
println(s"Running ${n}")
f.asInstanceOf[Function[String, T]]
}
}
val stringToInt = ((s: String) => s.toInt) :: HNil
val indexed = stringToInt zipWithIndex
val reported = indexed map reporter
// this is an `Any`, unfortunately
val result = reported.head("1")
The types appear correct before the map
, but I cannot for the life of me figure out where it's losing the type.
Note: this is running against Shapeless 2.3.0-SNAPSHOT.
Upvotes: 2
Views: 181
Reputation: 139038
You generally don't want to find yourself writing Nat
when using Shapeless except as an upper-bound constraint on a type parameter (or in some particular cases where you want to accept a literal integer value as a parameter and have it be available at the type level, but that's not relevant here).
In your case the view bound will get desugared to an implicit parameter of type F => (String => T, Nat)
, and the Scala compiler won't properly infer the T
. If I were less tired of thinking about Scala at the moment I could try to figure out why, but I'm not sure it matters much, since you don't want or need to be in this situation to start with—instead you can just add an N <: Nat
type parameter and skip the view bound entirely:
import shapeless._
object reporter extends Poly1 {
implicit def wrap[T, N <: Nat]: Case.Aux[(String => T, N), String => T] =
at[(String => T, N)] { fn =>
val f = fn._1
val n = fn._2
println(s"Running ${n}")
f
}
}
val stringToInt = ((s: String) => s.toInt) :: HNil
val indexed = stringToInt zipWithIndex
val reported = indexed map reporter
val result = reported.head("1")
This will work as expected and result
will be statically typed as an Int
.
Upvotes: 2