question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Implicit conversion for libraries dependent on refined (seperating `auto` to trait and object)

See original GitHub issue

Problem: Libraries which depend on refined types currently force the user to call import eu.timepit.refined.auto._ to allow standard type variables (literals) to be implicitly converted into their refined types.

Example:

  import eu.timepit.refined.api.Refined
  import eu.timepit.refined.api.Validate
  case class ZeroOrOne()
  implicit val zeroOrOneValidate: Validate.Plain[Int, ZeroOrOne] =
    Validate.fromPredicate(p => p == 0 || p == 1, p => s"($p is in not binary)", ZeroOrOne())

  def libFunc(x : Int Refined ZeroOrOne) : Int = x.get

libFunc(1) fails without the import

Solution (as discussed in gitter): Split refined’s auto into trait and object (see code). I recommend that the trait’s name will be more significant than auto.

This will allow the user to extend a companion object to the refined type from that trait, thus allowing the implicit conversion. So the example above changes into:

  import eu.timepit.refined.api.Refined
  import eu.timepit.refined.api.Validate
  case class ZeroOrOne()
  object ZeroOrOne extends eu.timepit.refined.api.auto //Or other name if chosen
  implicit val zeroOrOneValidate: Validate.Plain[Int, ZeroOrOne] =
    Validate.fromPredicate(p => p == 0 || p == 1, p => s"($p is in not binary)", ZeroOrOne())

  def libFunc(x : Int Refined ZeroOrOne) : Int = x.get

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:1
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
fthomascommented, Dec 26, 2016

Ok, applying this diff

--- a/modules/core/shared/src/main/scala-2.12/eu/timepit/refined/api/Refined.scala
+++ b/modules/core/shared/src/main/scala-2.12/eu/timepit/refined/api/Refined.scala
@@ -15,7 +15,7 @@ final class Refined[T, P] private (val value: T) extends AnyVal with Serializabl
     value.toString
 }
 
-object Refined {
+object Refined extends AutomaticConversions[Refined] {

--- a/modules/core/shared/src/main/scala/eu/timepit/refined/auto.scala
+++ b/modules/core/shared/src/main/scala/eu/timepit/refined/auto.scala
@@ -80,3 +80,12 @@ object auto {
       v: Validate[T, P]
   ): T @@ P = macro RefineMacro.impl[@@, T, P]
 }
+
+trait AutomaticConversions[F[_, _]] {
+
+  implicit def autoRefine[T, P](t: T)(implicit rt: RefType[F], v: Validate[T, P]): F[T, P] =
+    macro RefineMacro.impl[F, T, P]
+
+  implicit def autoUnwrap[T](tp: F[T, _])(implicit rt: RefType[F]): T =
+    rt.unwrap(tp)
+}

allows this usage with only one import that introduces the type alias type PosInt = Int Refined Positive:

Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102).
Type in expressions for evaluation. Or try :help.

scala> import eu.timepit.refined.types.all.PosInt
import eu.timepit.refined.types.all.PosInt

scala> 23: PosInt
res0: eu.timepit.refined.types.all.PosInt = 23

scala> -23: PosInt
<console>:16: error: Predicate failed: (-23 > 0).
       -23: PosInt
        ^

scala> res0: Int
res2: Int = 23

So for Refined types we can basically get rid off the extra auto._ import at the expense that users can’t opt out of the implicit conversions T => Refined[T, P] and Refined[T, P] => T. I need to think about the pros and cons of this approach to decide if we want to do this.

0reactions
soronpocommented, Dec 20, 2017

Thanks @fthomas. Nice update! You may now close this issue. I’m using singleton-ops which better fits my use-case.

Read more comments on GitHub >

github_iconTop Results From Across the Web

estatico/scala-newtype - Gitter
Hello, I have a question: does it make a difference to use map vs coerce ? I have a refined type which I...
Read more >
Proposal: Changes to Implicit Conversions - Scala Contributors
Conversion to the standard library, as a subtype of Function1 . Implicit conversions are changed to be given instances of the new type....
Read more >
Implicit Implications (part 3): The Future is Functional (implicitly)
These objects contain implicit conversions between Scala Iterables ... ability of the compiler to resolve dependant object types correctly.
Read more >
Implicit class vs Implicit conversion to trait - Stack Overflow
I'm trying to add new functions to existing types (so I can have the IDE auto suggest relevant functions ...
Read more >
5 Property Refinement / Resolution
During refinement the set of properties that apply to a formatting object is transformed into a set of traits that define constraints on...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found