Skip to content

Instantly share code, notes, and snippets.

@markhibberd
Created January 3, 2014 03:05
Show Gist options
  • Save markhibberd/8231912 to your computer and use it in GitHub Desktop.
Save markhibberd/8231912 to your computer and use it in GitHub Desktop.
argonaut union type example
package argonaut.example
import argonaut._, Argonaut._
import scalaz._, Scalaz._
object UnionExample extends {
sealed trait Thing
final case class One(n: String, i: Int) extends Thing
final case class Two(n: String) extends Thing
case object Three extends Thing
implicit def ThingEncodeJson: EncodeJson[Thing] =
EncodeJson(_ match {
case One(n, i) => Json("one" := Json("name" := n, "age" := i))
case Two(n) => Json("two" := Json("name" := n))
case Three => Json("three" := ())
})
implicit def ThingDecodeJson: DecodeJson[Thing] =
DecodeJson(c =>
tagged("one", c, jdecode2L(One.apply)("name", "age")) |||
tagged("two", c, jdecode1L(Two.apply)("name")) |||
tagged("three", c, implicitly[DecodeJson[Unit]].map(_ => Three)))
def tagged[A](tag: String, c: HCursor, decoder: DecodeJson[A]): DecodeResult[A] =
(c --\ tag).hcursor.fold(DecodeResult.fail[A]("Invalid tagged type", c.history))(decoder.decode)
}
@toby5box
Copy link

toby5box commented Apr 4, 2015

Mark, is there an update to this example? I get:

UnionExample.scala:21: type mismatch;
[error] found : argonaut.DecodeResult[UnionExample.Two]
[error] required: argonaut.DecodeResult[Product with Serializable with UnionExample.Thing]
[error] Note: UnionExample.Two <: Product with Serializable with UnionExample.Thing, but class DecodeResult is invariant in type A.
[error] You may wish to define A as +A instead. (SLS 4.5)
[error] tagged("two", c, jdecode1L(Two.apply)("name")) |||
[error] ^

@toby5box
Copy link

toby5box commented Apr 4, 2015

Never mind, it's possible to just widen the type to the common supertype, using another map[T], scalaz widen, or in my case, simple ascription of the supertype to a case object or case class constructor.

(h/t @tpolecat for leading me to the finish line on this one)

@mkalish
Copy link

mkalish commented Oct 4, 2016

Hi @toby5box... do you happen to have an updated example on how you got the gist working?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment