Last active
August 22, 2019 12:40
-
-
Save sortega/81d7a11ddc19afe0ac25c5de0981a7d7 to your computer and use it in GitHub Desktop.
Typeclasses sample code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fp.typeclasses | |
import org.apache.commons.text.StringEscapeUtils | |
sealed abstract class Json | |
object Json { | |
type JField = (String, Json) | |
case object JNull extends Json { | |
override def toString: String = "null" | |
} | |
final case class JString(s: String) extends Json { | |
override def toString: String = '"' + StringEscapeUtils.escapeJava(s) + '"' | |
} | |
final case class JNumber(value: Double) extends Json { | |
override def toString: String = value.toString | |
} | |
final case class JBool(value: Boolean) extends Json { | |
override def toString: String = value.toString | |
} | |
final case class JObject(fields: List[JField]) extends Json { | |
override def toString: String = | |
fields | |
.collect { | |
case (key, value) if value != JNull => | |
""""%s":%s""".format(StringEscapeUtils.escapeJava(key), value.toString) | |
} | |
.mkString("{", ",", "}") | |
} | |
final case class JArray(elems: List[Json]) extends Json { | |
override def toString: String = elems.mkString("[", ",", "]") | |
} | |
def obj(fields: (String, Json)*): JObject = JObject(fields.toList) | |
def arr(elems: Json*): JArray = JArray(elems.toList) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fp.typeclasses | |
trait Jsonable[A] { | |
def toJson(a: A): Json | |
} | |
object Jsonable { | |
implicit val stringJsonable: Jsonable[String] = (s: String) => Json.JString(s) | |
implicit val intJsonable: Jsonable[Int] = i => Json.JNumber(i.toDouble) | |
implicit def listJsonable[A](implicit J: Jsonable[A]): Jsonable[List[A]] = | |
elems => Json.JArray(elems.map(_.toJson)) | |
implicit def optionJsonable[A: Jsonable]: Jsonable[Option[A]] = { | |
case None => Json.JNull | |
case Some(a) => a.toJson | |
} | |
implicit def mapJsonable[A: Jsonable]: Jsonable[Map[String, A]] = | |
map => Json.JObject(map.mapValues(_.toJson).toList) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fp.typeclasses | |
final class JsonOps[A](val a: A) extends AnyVal { | |
def toJson(implicit J: Jsonable[A]): Json = J.toJson(a) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fp | |
package object typeclasses { | |
implicit def toJsonOps[A](a: A): JsonOps[A] = new JsonOps[A](a) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fp.typeclasses | |
import scalaz.Scalaz._ | |
object TypeclassesMain extends App { | |
// 1. Jsonable[A] | |
println("hello\nworld".toJson) | |
println(List(1, 23, 48).toJson) | |
println(List(EntityId("chat_message", "1"), EntityId("search", "XJ3")).toJson) | |
// println(List("hello", EntityId("search", "XJ3")).toJson) | |
println(some(3).toJson) | |
println(none[Int].toJson) | |
println( | |
Map( | |
"foo" -> Some(List(1, 2)), | |
"bar" -> Some(List(3)), | |
"buzz" -> None | |
).toJson | |
) | |
// 2. Typeclasses in the standard library: Num, Order | |
println(List(1, 7, 3).sorted) | |
println(List(EntityId("search", "XJ3"), EntityId("chat_message", "1")).sorted) | |
def sumOld[N](nums: List[N])(implicit N: Numeric[N]): N = nums.foldLeft(N.zero)(N.plus) | |
def sum[N](nums: List[N])(implicit N: Numeric[N]): N = { | |
import N._ | |
nums.foldLeft(zero)(_ + _) | |
} | |
println(sum(List(1, 2, 3))) | |
println(sum(List(1d, 2d, 3d))) | |
println(sum(List(BigDecimal(0.3), BigDecimal(0.4)))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And then import it explicitly