2016-01-11 8 views
5

SCodecの新しいユーザーとして、かなりの学習曲線があります。私は、ソースとドキュメントを読んでいても解決できないような障害にぶつかった。任意のネストされたコーデックを平坦化しますか?

私はこの

def packedByte : Codec[Int :: Int :: Int :: HNil] = uint(4) :: uint(2) :: uint(2) 

のような関数として人気の高いコーデックを定義し、この

case class MyPacket(foo : Boolean, first : Int, second : Int, third : Int, bar : Boolean) 
def packet : Codec[MyPacket] = (bool :: packedByte :: bool).as[MyPacket] 
のようなケースクラスから上位レベルにデコードし、このようなコーデックやエンコードにしてそれらを結合することができるようにしたいです

しかし、これは

はそのshapeless.::[Boolean,shapeless.::[shapを証明することができませんでしたと言って動作しません。 eless.::[Int,shapeless.::[Int,shapeless.::[Int,shapeless.HNil]]],shapeless.::[Boolean,shapeless.HNil]]]はcmd504.MyPacketに変換できます。 。

def packetInline : Codec[MyPacket] = (bool :: uint(4) :: uint(2) :: uint(2) :: bool).as[MyPacket] 

すべてのようなI "インライン" packedByteは、コンパイルしたときに、予想通り

しかし、動作します。私の直感は、コーデックは(エラーメッセージの2つのHNilsに基づいて) "平坦化"する必要があると言いますが、コーデック自体または内部のHList表現を平坦化できませんでした。

+0

最後に ':: HNil'なしでこれがどのように動作するのでしょうか? –

+1

@Łukasz[このメソッド](https://github.com/scodec/scodec/blob/v1.8.3/shared/src/main/scala/scodec/package.scala#L269) - 特別なScodec演算子です。シェイプレスの '::'ではありません。 –

+0

よろしくお願いします!それを知らなかった。 –

答えて

4

同様の状況で通常の値レベルのリストをどのように使用するかを考えて、ヒストリストの推論を開始すると便利なことがよくあります。例えば、我々は値とリストを持っているとします

val x = 0 
val xs = List(1, 2, 3) 

そして、私たちは前と後の両方xsxで新しいリストを作成したいです。我々+::+使用することができます。

scala> x +: xs :+ x 
res0: List[Int] = List(0, 1, 2, 3, 0) 

または:Scodecの場合

scala> x :: (xs :+ x) 
res1: List[Int] = List(0, 1, 2, 3, 0) 

を、何の+:オペレータはありませんが、そこ:::+があり、あなたは正確にあなたが同じようにそれらを使用することができます値のレベルでリストバージョンを使用してください。

import scodec._, scodec.codecs._, shapeless._ 

def packedByte: Codec[Int :: Int :: Int :: HNil] = 
    uint(4) :: uint(2) :: uint(2) 

case class MyPacket(
    foo: Boolean, 
    first: Int, 
    second: Int, 
    third: Int, 
    bar: Boolean 
) 

def packet: Codec[MyPacket] = (bool :: (packedByte :+ bool)).as[MyPacket] 

ネスティングを構成することは可能ですdヒットしてからそれを平坦化しますが、:+ははるかに慣用的です。

+0

ああ、ちょうど昨夜:+演算子を発見しましたが、関連性に関するコンパイラの不満のために使用するのに問題がありました。それらの括れがキーのように見えます。ご協力いただきありがとうございます! – RAX

関連する問題