不整形的HList文字类型被删除了吗?

时间:2018-10-22 06:49:22

标签: scala shapeless hlist

我正在尝试按文字类型过滤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

2 个答案:

答案 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
相关问题