在Scalaz状态monad中查找Shapeless HList的类型类实例

时间:2015-02-23 16:55:39

标签: scala type-inference scalaz shapeless

假设我有一个状态monad,状态是HList,我定义了一个组合器,它接受了n的第一个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

scala编译器在类型推断期间卡住了。它并未推断S的{​​{1}}类型参数是take。因此,编译器无法找到参数Int :: String :: HNil的隐式值。

tk

我知道我可以通过简单地公开状态或修复[error] could not find implicit value for parameter tk: shapeless.ops.hlist.Take[S,shapeless.Nat._1.N] [error] _ <- take(_1) 来帮助编译器。但我不想!这些额外信息似乎是多余的:

S

为什么在第一个代码段中,scala编译器将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 推断为S而不是Nothing?我想知道是否可以在不暴露状态或提供类型信息的情况下使其工作?

提前致谢!

1 个答案:

答案 0 :(得分:0)

以下编译:

for {
  _ <- init[Int :: String :: HNil] flatMap { _  => take(_1) }
  x <- state("abc")
} yield x

问题的for - 循环大致翻译为

init[Int :: String :: HNil] flatMap { _ =>
  take(_1) flatMap { _ =>
    state("abc") map { x =>
      x
    }
  }
}

并且scalac似乎不愿意推断take(_1)的类型参数,因为它已经必须推断它下面的某些类型并且直接在其上调用flatMap