Find type class instance for Shapeless HList in Scalaz state monad
Say that I have a state monad with the state is an HList
and I define a combinator that takes the first n
elements of this HList
:
import scalaz._, Scalaz._
import shapeless._, ops.hlist._, Nat._
def take[S <: HList](n: Nat)(implicit tk: Take[S, n.N]):
IndexedState[S, tk.Out, Unit] = ???
for {
_ <- init[Int :: String :: HNil]
_ <- take(_1)
x <- state("abc")
} yield x
The scala compiler gets stuck during type inference. It doesn't infer that the S
type parameter of take
is an Int :: String :: HNil
. Thus, the compiler cannot find implicit value for parameter tk
.
[error] could not find implicit value for parameter tk: shapeless.ops.hlist.Take[S,shapeless.Nat._1.N]
[error] _ <- take(_1)
I know that I can help the compiler by simply exposing the state or by fixing S
. But I don't want to! This extra-information seems redundant:
def take[S <: HList](hl: S, n: Nat)(implicit tk: Take[S, n.N]):
IndexedState[S, tk.Out, Unit] = ???
for {
hl <- init[Int :: String :: HNil]
_ <- take(hl, _1) // Redundant
_ <- take[Int :: HNil](_1) // Redundant
x <- state("abc")
} yield x
Why in the first code snippet, scala compiler inferred S
as Nothing
instead of Int :: String :: HNil
? I'm wondering if its possible to get this works without exposing the state or giving type information?
Thanks in advance!
The following compiles:
for {
_ <- init[Int :: String :: HNil] flatMap { _ => take(_1) }
x <- state("abc")
} yield x
The for
-loop of your question is roughly translated to
init[Int :: String :: HNil] flatMap { _ =>
take(_1) flatMap { _ =>
state("abc") map { x =>
x
}
}
}
and scalac seems not willing to infer the type argument of take(_1)
given that it already has to infer some types below it and you call flatMap
directly on it.
上一篇: 在Haskell中查找类型签名