有没有一种方法可以以通用方式将Hlist转换为适当的案例类?

时间:2020-05-29 11:54:29

标签: scala functional-programming shapeless hlist

我看过特拉维斯·布朗(Travis Brown)提出的炫酷solution,它允许以通用方式在彼此之间转换案例类。我尝试使用它将 HttpListener listener2 = new HttpListener(); listener2.Prefixes.Clear(); listener2.Prefixes.Add("http://+:4200/"); listener2.Prefixes.Add("http://XXX.XXX.eu/"); listener2.Start(); LogWriteLine("http listener started listening to: " +listener2.Prefixes); try { while (true)//change to match end check { LogWriteLine("http listener waiting"); HttpListenerContext context = listener2.GetContext(); LogWriteLine("http request arrived"); HttpListenerRequest request = context.Request; // Obtain a response object. HttpListenerResponse response = context.Response; System.IO.Stream body = request.InputStream; System.Text.Encoding encoding = request.ContentEncoding; System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding); if (!request.HasEntityBody) { LogWriteLine("No client data was sent with the request."); Thread.Sleep(300); //return; } if (request.ContentType != null) { LogWriteLine("Client data content type " + request.ContentType); } LogWriteLine("Client data content length " + request.ContentLength64); //Works fine LogWriteLine("Start of client data:"); // Convert the data to a string and display it on the console. Console.WriteLine(body.CanSeek); string s = reader.ReadToEnd(); var ahoj = new StreamReader(context.Request.InputStream).ReadToEnd(); Console.WriteLine("ahoj length " + ahoj.Length); //0 Console.WriteLine(s); //nothing string text; var bytes = default(byte[]); using (var reader1 = new StreamReader(request.InputStream, request.ContentEncoding)) { text = reader1.ReadToEnd(); Console.WriteLine(text + text.Length); //output: 0 using (var memstream = new MemoryStream()) { reader1.BaseStream.CopyTo(memstream); bytes = memstream.ToArray(); } Console.WriteLine("bytes:" + bytes.Length); //output: bytes: 0 } LogWriteLine("End of client data:"); //write to console file sw.Write(s); body.Close(); reader.Close(); } } catch (Exception ex) { Console.WriteLine(ex); } 转换为HList,但没有设法使其正常工作。这是我的尝试:

case class

不幸的是,它失败并显示以下错误:

import shapeless._, ops.hlist.Align
import syntax.std.tuple._

object Shplss  extends App {
  class SameFieldsConverter[T] {
    def apply[S, SR <: HList, TR <: HList](s: S)(implicit
                                                 genS: LabelledGeneric.Aux[S, SR],
                                                 genT: LabelledGeneric.Aux[T, TR],
                                                 align: Align[SR, TR]
    ) = genT.from(align(genS.to(s)))
  }

  def convertTo[T] = new SameFieldsConverter[T]

  type SomeType = Int :: Int :: String :: Boolean :: Int :: Int :: HNil
  final case class SomeProductType(f1: Int, f2: Int, f3: String, f4: Boolean, f5: Int, f6: Int)

  val some: SomeType = (4, 4, "ssdf", true, 2, 4).productElements

  convertTo[SomeProductType](some)
}

是否有一种增强Error:(22, 29) could not find implicit value for parameter genS: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeType,SR] convertTo[SomeProductType](some) Error:(22, 29) not enough arguments for method apply: (implicit genS: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeType,SR], implicit genT: shapeless.LabelledGeneric.Aux[com.test.Shplss.SomeProductType,TR], implicit align: shapeless.ops.hlist.Align[SR,TR])com.test.Shplss.SomeProductType in class SameFieldsConverter. Unspecified value parameters genS, genT, align. convertTo[SomeProductType](some) 函数的方法,使其也可以在converTo[B]之间转换?

1 个答案:

答案 0 :(得分:5)

Shapeless的GenericLabelledGeneric是类型类,它们为使用hlists和coproducts的案例类和密封特性层次提供通用表示。如果您已经有了一个hlist,则实际上不需要Generic实例,而Shapeless不提供实例。就您而言,这意味着您实际上可以跳过genSSR部分:

import shapeless._, ops.hlist.Align
import syntax.std.tuple._

object Shplss  extends App {
  class SameFieldsConverter[T] {
    def apply[S <: HList, TR <: HList](s: S)(implicit
      genT: Generic.Aux[T, TR],
      align: Align[S, TR]
    ) = genT.from(align(s))
  }

  def convertTo[T] = new SameFieldsConverter[T]

  type SomeType = Int :: Int :: String :: Boolean :: Int :: Int :: HNil
  final case class SomeProductType(f1: Int, f2: Int, f3: String, f4: Boolean, f5: Int, f6: Int)

  val some: SomeType = (4, 4, "ssdf", true, 2, 4).productElements

  convertTo[SomeProductType](some)
}

这将给您SomeProductType(4,4,ssdf,true,2,4),如您所愿。

请注意,由于我们不再具有要在输入侧对齐的标签,因此我已将genTLabelledGeneric更改为Generic。我猜您可以添加一些额外的机制来将未标记的输入“注入”到Shapeless记录中,以匹配LabelledGeneric类型,但是在这种特定的用例中,至少没有任何意义。

相关问题