Tagged Types

sbt configuration

/***
libraryDependencies += "io.argonaut" %% "argonaut-scalaz" % "6.2"
*/

Common imports

import argonaut._
import argonaut.Argonaut._
import scalaz._
import scalaz.Scalaz._

A tagged type for email strings

sealed trait EmailTag
type Email = String @@ EmailTag

val email: Email = Tag[String, EmailTag]("james@earldouglas.com")

Encoding

implicit val encodeEmail: EncodeJson[Email] =
  EncodeJson { x: Email => jString(Tag.unwrap(x)) }

val encodedEmail: String = email.asJson.spaces2

println(s"\nencoded Email:\n$encodedEmail")

Decoding

implicit val decodeEmail: DecodeJson[Email] =
  DecodeJson { _.as[String] map { Tag[String, EmailTag](_) } }

val decodedEmail: Either[String, Email] =
  "\"james@earldouglas.com\"".decodeEither[Email]

println(s"\ndecoded Email:\n$decodedEmail")

Demo

This file is literate Scala, and can be run using Codedown:

$ curl https://earldouglas.com/scala/argonaut/tagged.md |
  codedown scala > script.scala
$ sbt -Dsbt.main.class=sbt.ScriptMain script.scala

encoded Email:
"james@earldouglas.com"

decoded Email:
Right(james@earldouglas.com)