Бесформенные литеральные типы HList стерты? - PullRequest
0 голосов
/ 22 октября 2018

Я пытаюсь отфильтровать 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 голосов
/ 02 ноября 2018

Это то, как я делаю это на 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
0 голосов
/ 22 октября 2018

Полагаю, это работает с 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 на X для Typelevel Scala.

...