admin 管理员组

文章数量: 1086019

scala2.12 l have a list of different scodec.codecs ig. List(int(8),floatL,uint,...) and this list is very long.

How can i get a Codec[int(8)::floatL::uint::...::HNIL]?

I know i can do it mannualy but it cost a lot.

i tried foldLeft using codec.deriveHNil as the first param,but it turns out to be the wrong type

now i am able to add more information. i am now parsing a binary file.its hearder part contains the information of all params the data part contains, among which the most important is the frequence (each param has a different frequence and hence has different.number of values in one second/frame).following the header part is the data part,it is stored one frame after other,in every frame each param is stored one after one other(paramsA's {{frequentA}} values followed by paramB's {{frequentB}} values). there are about 300 params in the file. how can i parse this file?

the list of codecs is what i can get from the header part,but i donot know what to do next

in fact every param is a list of float values, the differences between param is that different param has different frequency(number of values per second)

scala2.12 l have a list of different scodec.codecs ig. List(int(8),floatL,uint,...) and this list is very long.

How can i get a Codec[int(8)::floatL::uint::...::HNIL]?

I know i can do it mannualy but it cost a lot.

i tried foldLeft using codec.deriveHNil as the first param,but it turns out to be the wrong type

now i am able to add more information. i am now parsing a binary file.its hearder part contains the information of all params the data part contains, among which the most important is the frequence (each param has a different frequence and hence has different.number of values in one second/frame).following the header part is the data part,it is stored one frame after other,in every frame each param is stored one after one other(paramsA's {{frequentA}} values followed by paramB's {{frequentB}} values). there are about 300 params in the file. how can i parse this file?

the list of codecs is what i can get from the header part,but i donot know what to do next

in fact every param is a list of float values, the differences between param is that different param has different frequency(number of values per second)

Share Improve this question edited Mar 30 at 23:16 Dmytro Mitin 51.8k3 gold badges32 silver badges73 bronze badges asked Mar 28 at 4:29 ruoyuruoyu 32 bronze badges 3
  • 4 The first is an object and the second is a type, so it is not clear what you are trying to do. It might help if you posted the manual code for people unfamiliar with scodec (like me) but it looks like a flatten or fold or reduce operation of some kind. – Tim Commented Mar 28 at 7:04
  • Please add more information to your question: what scala version are you using? What Codec do you want to obtain (a circe.io.Codec maybe?)? What type is int(8)::floatL::uint::... supposed to be (a shapeless.HListmaybe?)? – MartinHH Commented Mar 28 at 7:41
  • 1 Thanks for updating your question. I'd expect that one could do this with shapeless if the input type is acutally an HList of codecs and not a simple List(!), but I'm not a shapeless expert. – MartinHH Commented Mar 28 at 9:44
Add a comment  | 

2 Answers 2

Reset to default 2

There is a problem in your question that cannot be solved: you only know the type of the desired Codec at runtime, but you try to create a Codec for a specific type as if it were known at compiletime.

If the type of your input is List[Codec[_]] (a list of Codecs of unknown types), the best you can get is a Codec[? <: HList] (a Codec for an HList of unknown type). That, you could do as follows:

import scodec._
import shapeless.HList
import shapeless.HNil

object ListOfCodecsToCodecHList {

  def convert(list: List[Codec[_]]): Codec[? <: HList] = {
    list.foldRight[Codec[? <: HList]](Codec[HNil]) { (codec, acc) =>
      codec :: acc
    }
  }

}

That should enable you to parse your file, but the compile-time type of the parsed frames will remain unknown.

If you actually need Codec[Frame] (Codec[int(8) :: floatL :: uint :: ... :: HNil] doesn't make sense) you can adopt @MartinHH's solution slightly, generating Codec[List[A]] rather than Codec[? <: HList]:

def convert[A](list: List[Codec[A]]): Codec[List[A]] =
  list.foldRight[Codec[List[A]]](Codec[HNil].xmap(_ => Nil, _ => HNil)) {
    (codec: Codec[A], acc: Codec[List[A]]) =>
      (codec ~ acc).xmap(
        (a: A, as: List[A]) => a :: as,
        { case a :: as => (a, as) }
      )
  }

Then

case class ParamInfo(freq: Int)
case class Param(values: List[Float])
case class Frame(params: List[Param])

val infos = (1 to 5).map(i => ParamInfo(32 * i)).toList

val codecList: List[Codec[Param]] =
  infos.map(info => fixedSizeBits(info.freq, list(float).as[Param]))

val combined: Codec[Frame] = convert(codecList).as[Frame]

combined
  .encode(
    Frame(
      List(
        Param(List(1)),
        Param(List(2, 3)),
        Param(List(4, 5, 6)),
        Param(List(7, 8, 9, 10)),
        Param(List(11, 12, 13, 14, 15))
      )
    )
  )
  .map(_.toBin)
//Successful(001111111000000000000000000000000100000000000000000000000000000001000000010000000000000000000000010000001000000000000000000000000100000010100000000000000000000001000000110000000000000000000000010000001110000000000000000000000100000100000000000000000000000001000001000100000000000000000000010000010010000000000000000000000100000100110000000000000000000001000001010000000000000000000000010000010101000000000000000000000100000101100000000000000000000001000001011100000000000000000000)

combined.decode(
  bin"001111111000000000000000000000000100000000000000000000000000000001000000010000000000000000000000010000001000000000000000000000000100000010100000000000000000000001000000110000000000000000000000010000001110000000000000000000000100000100000000000000000000000001000001000100000000000000000000010000010010000000000000000000000100000100110000000000000000000001000001010000000000000000000000010000010101000000000000000000000100000101100000000000000000000001000001011100000000000000000000"
)//Successful(DecodeResult(Frame(List(Param(List(1.0)), Param(List(2.0, 3.0)), Param(List(4.0, 5.0, 6.0)), Param(List(7.0, 8.0, 9.0, 10.0)), Param(List(11.0, 12.0, 13.0, 14.0, 15.0)))),BitVector(empty)))


https://scastie.scala-lang./DmytroMitin/tpEHXF70SJ2BymyAR2Wd2w/3

本文标签:

Error[2]: Invalid argument supplied for foreach(), File: /www/wwwroot/roclinux.cn/tmp/view_template_quzhiwa_htm_read.htm, Line: 58
File: /www/wwwroot/roclinux.cn/tmp/route_read.php, Line: 205, include(/www/wwwroot/roclinux.cn/tmp/view_template_quzhiwa_htm_read.htm)
File: /www/wwwroot/roclinux.cn/tmp/index.inc.php, Line: 129, include(/www/wwwroot/roclinux.cn/tmp/route_read.php)
File: /www/wwwroot/roclinux.cn/index.php, Line: 29, include(/www/wwwroot/roclinux.cn/tmp/index.inc.php)