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.

链接地址: http://www.djcxy.com/p/43058.html

上一篇: 在Haskell中查找类型签名

下一篇: 在Scalaz状态monad中查找Shapeless HList的类型实例