From 8fef53d44a57008dea411b882b12bc3d5d1ca2e0 Mon Sep 17 00:00:00 2001 From: Sergey Nastich Date: Wed, 12 Sep 2018 16:10:17 -0400 Subject: Add `Trimmed` tag and its logic (revisited) (#215) * Add option and iterable converters for transparent `@@ Trimmed` creation. * Move tagging stuff to a separate package - relieve `core.scala` from some extra code. * Add Tagging stuff and publishing section to README.md --- src/main/scala/xyz/driver/core/core.scala | 25 ++------- .../scala/xyz/driver/core/tagging/tagging.scala | 62 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 src/main/scala/xyz/driver/core/tagging/tagging.scala (limited to 'src/main') diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index 846bed3..2ab4e88 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -1,16 +1,15 @@ package xyz.driver -import scalaz.{Equal, Monad, OptionT} import eu.timepit.refined.api.{Refined, Validate} import eu.timepit.refined.collection.NonEmpty +import scalaz.{Equal, Monad, OptionT} import xyz.driver.core.rest.errors.ExternalServiceException +import xyz.driver.core.tagging.Tagged import scala.concurrent.{ExecutionContext, Future} // TODO: this package seems too complex, look at all the features we need! -import scala.language.reflectiveCalls -import scala.language.higherKinds -import scala.language.implicitConversions +import scala.language.{higherKinds, implicitConversions, reflectiveCalls} package object core { @@ -29,14 +28,7 @@ package object core { } } - object tagging { - private[core] trait Tagged[+V, +Tag] - - implicit class Taggable[V <: Any](val v: V) extends AnyVal { - def tagged[Tag]: V @@ Tag = v.asInstanceOf[V @@ Tag] - } - } - type @@[+V, +Tag] = V with tagging.Tagged[V, Tag] + type @@[+V, +Tag] = V with Tagged[V, Tag] implicit class OptionTExtensions[H[_]: Monad, T](optionTValue: OptionT[H, T]) { @@ -129,13 +121,4 @@ package core { final case class Base64(value: String) - trait Trimmed - - object Trimmed { - import tagging._ - - implicit def string2Trimmed(str: String): String @@ Trimmed = str.trim().tagged[Trimmed] - - implicit def name2Trimmed[T](name: Name[T]): Name[T] @@ Trimmed = Name[T](name.value.trim()).tagged[Trimmed] - } } diff --git a/src/main/scala/xyz/driver/core/tagging/tagging.scala b/src/main/scala/xyz/driver/core/tagging/tagging.scala new file mode 100644 index 0000000..5b6599e --- /dev/null +++ b/src/main/scala/xyz/driver/core/tagging/tagging.scala @@ -0,0 +1,62 @@ +package xyz.driver.core + +import scala.collection.generic.CanBuildFrom +import scala.language.{higherKinds, implicitConversions} + +/** + * @author sergey + * @since 9/11/18 + */ +package object tagging { + + implicit class Taggable[V <: Any](val v: V) extends AnyVal { + def tagged[Tag]: V @@ Tag = v.asInstanceOf[V @@ Tag] + } + +} + +package tagging { + + sealed trait Tagged[+V, +Tag] + + object Tagged { + implicit class TaggedOps[V, Tag](val v: V @@ Tag) extends AnyVal { + def tagless: V = v + } + + implicit def orderingMagnet[V, Tag](implicit ord: Ordering[V]): Ordering[V @@ Tag] = + ord.asInstanceOf[Ordering[V @@ Tag]] + + } + + sealed trait Trimmed + + object Trimmed { + + implicit def apply[V](trimmable: V)(implicit ev: CanBeTrimmed[V]): V @@ Trimmed = { + ev.trim(trimmable).tagged[Trimmed] + } + + sealed trait CanBeTrimmed[T] { + def trim(trimmable: T): T + } + + implicit object StringCanBeTrimmed extends CanBeTrimmed[String] { + def trim(str: String): String = str.trim() + } + + implicit def nameCanBeTrimmed[T]: CanBeTrimmed[Name[T]] = new CanBeTrimmed[Name[T]] { + def trim(name: Name[T]): Name[T] = Name[T](name.value.trim()) + } + + implicit def option2Trimmed[V: CanBeTrimmed](option: Option[V]): Option[V @@ Trimmed] = + option.map(Trimmed(_)) + + implicit def coll2Trimmed[T, C[_] <: Traversable[_]](coll: C[T])( + implicit ev: C[T] <:< Traversable[T], + tr: CanBeTrimmed[T], + bf: CanBuildFrom[Nothing, T @@ Trimmed, C[T @@ Trimmed]]): C[T @@ Trimmed] = + ev(coll).map(Trimmed(_)(tr)).to[C] + } + +} -- cgit v1.2.3