我正在尝试按文字类型过滤HList,但无法使其正常工作,它只会过滤所有字符串:
import shapeless._
import shapeless.ops.hlist._
def filterLabel[Labels <: HList, Label, Out <: HList](labels: Labels, label: Label)(
implicit sel: Filter.Aux[Labels, label.type, Out]): Out = sel(labels)
val a: "a" = "a"
val b: "b" = "b"
val c1: 1 = 1
val h1 = a :: b :: a :: c1 :: HNil
//result: hl: String :: String :: String :: Int :: HNil = "a" :: "b" :: "a" :: 1 :: HNil
//looks like literal-types are no longer present?
filterLabel(h1, "a")
我使用Scala org.typelevel 2.12.4-bin-typelevel-4进行了测试。 应该可以吗? HList是否应该保持文字类型?
该代码可在Scala中使用带有编译器选项“ -Yliteral-types”的Scala 2.12运行。 例如炸药:
curl -s https://raw.githubusercontent.com/typelevel/scala/typelevel-readme/try-typelevel-scala.sh | bash
repl.compiler.settings.YliteralTypes.value = true
import $ivy.`com.chuusai::shapeless:2.3.3`, shapeless._, shapeless.ops.hlist._
//now paste the above code
更新: 现在,我仅拥有Lightbend Scala的以下内容:
import shapeless._
import shapeless.ops.hlist._
import syntax.singleton._
implicit def stringToF(label: String) = () => label.narrow
def filterLabel[Labels <: HList, T, Label <: String, Out <: HList](labels: Labels, label: () => Label)(
implicit
sel: Filter.Aux[Labels, Label, Out]): Out = sel(labels)
val h1 = "a".narrow :: "b".narrow :: "a".narrow :: "c".narrow :: HNil
filterLabel(h1, "a")
//res92: a :: a :: HNil = "a" :: "a" :: HNil
它还可以处理带有文字类型参数的对象列表:
import shapeless._
import shapeless.ops.hlist._
import syntax.singleton._
class MyLabel[L <: String](label: L)
object MyLabel {
def apply(label: String) = new MyLabel(label.narrow)
}
implicit def stringToMyLabel(label: String) = new MyLabel(label.narrow)
def filterLabel[Labels <: HList, T, Label <: String, Out <: HList](labels: Labels, label: MyLabel[Label])(
implicit
sel: Filter.Aux[Labels, MyLabel[Label], Out]): Out = sel(labels)
val h1 = MyLabel("a") :: MyLabel("b") :: MyLabel("a") :: MyLabel("c") :: HNil
filterLabel(h1, "a")
//res88: MyLabel[a] :: MyLabel[a] :: HNil = ammonite.$sess.cmd83$MyLabel@55a5d73c :: ammonite.$sess.cmd83$MyLabel@eb78e11 :: HNil
答案 0 :(得分:1)
我想这可以与Lightbend Scala一起使用:
import shapeless.ops.hlist.Filter
import shapeless.{::, HList, HNil, Witness}
import shapeless.syntax.singleton._
def filterLabel[Labels <: HList, Label, Out <: HList](labels: Labels, label: Label)(
implicit sel: Filter.Aux[Labels, Label, Out]): Out = sel(labels)
val h1: Witness.`"a"`.T :: Witness.`"b"`.T :: Witness.`"a"`.T :: Witness.`1`.T :: HNil =
"a".narrow :: "b".narrow :: "a".narrow :: 1.narrow :: HNil
filterLabel(h1, "a".narrow) // a :: a :: HNil
您可以尝试将Witness.`X`.T
替换为Typelevel Scala的X
。
答案 1 :(得分:0)
这就是我在Typelevel scala 2.12.4上做到的方式
trait Narrow[T] {
def value: T
}
object Narrow {
def apply[T](implicit n: Narrow[T]): n.type = n
implicit def hnil = new Narrow[HNil] { def value = HNil }
implicit def cons[T, L <: HList: Narrow](implicit t: ValueOf[T]) = new Narrow[T::L] {
def value = t.value :: Narrow[L].value
}
}
然后在REPL上
scala> val h1 = Narrow["a"::"b"::"a"::1::HNil].value
h1: "a" :: "b" :: "a" :: 1 :: shapeless.HNil = a :: b :: a :: 1 :: HNil