Git Product home page Git Product logo

scala-newtype's People

Contributors

abalonperin avatar carymrobbins avatar jatcwang avatar jhnsmth avatar jorokr21 avatar jozic avatar kailuowang avatar liff avatar xuwei-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scala-newtype's Issues

Illegal cyclic reference error when abstract companion

I suppose the companion objects aren't working as expected when they have a type hierarchy.
Consider a simple example:

  1. I have some re-usable companion:
abstract class AbstractObjectCompanion[T] {
  def apply(src: Int): T
  implicit class Ops(t: T) {
    def print = t.toString
  }
}
  1. And its implementation here:
import io.estatico.newtype.macros.newtype

package object some {
  @newtype class MyInt(val i: Int)
  object MyInt extends AbstractObjectCompanion[MyInt] {
    override def apply(src: Int): MyInt = new MyInt(src)
  }
}

... does not compile:

illegal cyclic reference involving type MyInt
  object MyInt extends AbstractObjectCompanion[MyInt] {

But it compiles without @newtype OR without AbstractObjectCompanion.

Support Array casting

@alexknvl pointed out that it's possible to encode newtypes in such a way that casting Arrays with asInstanceOf will work (which means Coercible can work too).

Here's a simple adaptation from his solution to demonstrate a failing test case.

object Example {

  class Foo[A](val a: Array[A])

  val foo = new Foo(Array(1, 2, 3))

  def subst[F[_], T](fa: F[Int]): F[T] = fa.asInstanceOf[F[T]]

  type Good = Good.Type
  object Good {
    type Base <: Any
    trait Tag extends Any
    type Type <: Base with Tag
  }

  def good() = println(subst[Foo, Good](foo).a.head)

  @newtype case class Bad(value: Int)

  def bad() = println(subst[Foo, Bad](foo).a.head)

  def main(args: Array[String]): Unit = {
    good()
    bad()
  }
}

Ability to specify lower bound of Null

If we try this:

  @newsubtype final case class Foo(value: Integer)

  implicitly[Null <:< Foo]

Then it fails to compile with:

[error] Cannot prove that Null <:< web.base.react.package.Foo.
[error]   implicitly[Null <:< Foo]
[error]             ^

Would it be possible that if Repr <: AnyRef then Type becomes:

type Type >: Null <: Base with Tag

Inconsistent type alias expansion

It seems that encoding newtypes with a "normal" type alias means that scalac can expand it at will. We need to change the encoding from

type Type[..] = Base with Tag[..]

to

type Type[..] <: Base with Tag[..]

See scala/bug#10750

Warning with -Xsource:2.14

On Scala 2.13 with -Xsource:2.14 compiler option, newtype macro gives the following warning

Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method hashCode, 
or remove the empty argument list from its definition (Java-defined methods are exempt).
In Scala 3, an unapplied method like this will be eta-expanded into a function.

It makes newtypes unusable with both this option and -Xfatal-warnings enabled

Support @newsubtype for value classes

I needed a new sub-type / tagged type for a value class. It had to be a sub-type because I needed to use it in all the places where the base type could be used but perhaps more importantly I needed all the implicit conversions to be found from its companion object.

The problem with @newsubtype is that it doesn't support value classes. One reason is because the Ops$newtype is a value class which cannot wrap another user-defined value class.

I tried doing something more like what Shapeless does but then I run into a bunch of ClassCastExceptions. I initially reported that in scala-js/scala-js#4778 as I thought it was a Scala.js specific issue but that turns out to be untrue. I found a bunch of related Shapeless issues (see that issue for links).

I started wondering how it was that @newtype avoided these ClassCastExceptions (and as hinted by Miles in some of his comments that Shapeless 3 may change Tagged back to how it was). It seems that the structural type is the key here.

We of course need the type we are extending somewhere in Type for it to be a subtype but it can't be in Base.

This encoding seems to do the trick:

import scala.language.implicitConversions

object Main {

  final class KeyAddingStage(private val args: Array[Any]) extends AnyVal

  object KeyAddingStage {
    implicit def build(stage: KeyAddingStage): String = stage.toString
  }

  type RenderedProps[Props] = RenderedProps.Type[Props]

  object RenderedProps {
    type Base = {
      type __RenderedProps__newtype
    }

    trait Tag[Props] extends Any

    type Type[Props] <: Base with KeyAddingStage with Tag[Props]

    def apply[Props](stage: KeyAddingStage): RenderedProps[Props] = stage.asInstanceOf[RenderedProps[Props]]
  }

  object Name {
    case class Props(name: String)

    def component(props: Props): KeyAddingStage = new KeyAddingStage(
      Array(
        props.asInstanceOf[Any]
      )
    )

    def apply(name: String): RenderedProps[Props] = RenderedProps(component(Props(name)))
  }

  def main(args: Array[String]): Unit = {
    val first: RenderedProps[Name.Props] = Name("Jason")
    val firstStage: KeyAddingStage = first
    val str: String = first
    println(first == firstStage)
    val props: Seq[RenderedProps[Name.Props]] = Seq(first)
    val propsHead: RenderedProps[Name.Props] = props.head
    println(firstStage == propsHead)
  }
}

Any thoughts on adding something like this so that we can have @newsubtype support for value classes?

ClassTag instances can cause runtime exceptions

ClassTags are used by scalac during type-based pattern matching. This is a problem for newtypes (but not newsubtypes) since their ClassTag runtime class is Object. As such, we are permitting users via our "safe" API to do unsafe things without it being obvious that what they are doing will definitely result in a runtime exception.

scala> import io.estatico.newtype.macros._, io.estatico.newtype.ops._

scala> @newtype case class Foo(x: String)

scala> (1: Any) match { case x: Foo => x ; case _ => Foo("nope") }
res0: Foo = 1

scala> res0.coerce[String]
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
  ... 38 elided

I think the solution for now is to remove ClassTag instances altogether. The only reason I think they're useful is for constructing Arrays, but I think this is the wrong solution. I have an experimental (and incomplete) branch for a different way of handling Arrays here (via an AsArray type class). I'm looking to try to use this to resolve #10 in a type safe way.

In the meantime, I think it's best to remove the ClassTag instances to prevent unsafe code from happening by accident.

Also see my original point about this with regard to the unapply method here.

Support @newtype case classes if not inside object

I'm making a web app and using newtypes to for type-safe IDs for different model types.

As there are quite a few model types, I tried to move type code into a trait that can be mixed into companion object:

trait OwnIdType {
  @newtype case class ID(toInt: Int)

  object ID {
    // Circe things
    implicit val toJson: Encoder[ID] = deriving
    implicit val fromJson: Decoder[ID] = deriving
  }
}

That didn't work, however, telling me that fields can only be used if the newtype is defined inside an object

Ultimately I wrote case class boilerplate myself:

trait OwnIdType {
  @newtype class ID(underlying: Int)

  object ID {
    def apply(value: Int): ID = value.coerce

    implicit class Ops(val id: ID) {
      def toInt: Int = id.coerce
    }

    implicit val toJson: Encoder[ID] = deriving
    implicit val fromJson: Decoder[ID] = deriving
  }
}

It compiles and works, and the only significant difference is that Ops class cannot extend AnyVal.

Is it possible to support @newtype case class inside traits by dropping extends AnyVal on ops class?

Provide a way to generically provide instances for all new types for a certain type class

In some use cases, for some type classes I just want to provide instances for all new types based on the instances of their base class. E.g a circe Json encoder (or the Format in play json).
The solution I have now is like the following, but it's tied to the legacy encoding and too coupled to the implementation detail:

trait BaseAutoDerive[F[_]] extends LowerPriorityAudoDerive[F] {
  implicit def newTypeDerive[Base, Repr, Tag](implicit ev: F[Repr]): F[BaseNewType.Aux[Base, Tag, Repr]] =
    ev.asInstanceOf[F[BaseNewType.Aux[Base, Tag, Repr]]]
}

trait LowerPriorityAudoDerive[F[_]] {
  implicit def newTypeDeriveForRepr_[Tag, Repr_](implicit ev: F[Repr_]):
  F[BaseNewType.Aux[AnyRef{type Repr = Repr_}, Tag, Repr_]] =
    ev.asInstanceOf[F[BaseNewType.Aux[AnyRef{type Repr = Repr_}, Tag, Repr_]]]
}

Then you can do

object autoFormatDerive extends BaseAutoDerive[Format]
import autoFormatDerive._

Note that a simpler Coercible solution doesn't work, namely the following doesnt resolve the implicts

implicit def coercibleEq[A, B](implicit ev: Coercible[B, A], B: Eq[B]): Eq[A] =
   B.asInstanceOf[Eq[A]]

"+" method shadowed by any2stringadd

Hi! Thanks for a wonderful library.

We're hitting an interesting issue:

@newtype case class Demo(value: Int) {
  def +(another: Demo): Demo = ???
}

def demo(d: Demo) = d + d
                      ^ type mismatch;
 found   : (...).Demo
    (which expands to)  (...).Demo.Type
 required: String

If I just say d +, I get missing argument list for method + in class any2stringadd. As far as I could find out, that method gets special treatment and can't be unimported.

I took a look at the implementation of newtypes and as far as I could tell methods from the class are moved to an implicit class next to it, to which a conversion called Demo.Ops$newtype is applied - when I apply it manually, or import it (import Demo._ or by exact name) it compiles as expected. I assume any2stringadd just has higher precedence because it's imported.

Is there something scala-newtype can do to allow this name in methods on newtypes?

Generate unapply for newtype case class

I'm starting to use more and more of this library. In particular, newtypes are quite useful for defining custom typeclass instances:

@newtype case class FirstOf[A](value: A)
object FirstOf {
   implicit def semigroup[A]: Semigroup[A] = Semigroup.instance((a, _) => a)
}

It would be really nice if for these cases unapply would also be generated. This comes in handy in chains involving foldMap, e.g.

list
  .foldMap(person => Map(person.name -> FirstOf(person.age))
  .map { case (name, FirstOf(age)) => ??? } // no need to use `.value` manually

Dealing with NoClassTag when converting to arrays

Hello ๐Ÿ‘‹

I have a very simple case and I couldn't find documentation on how to deal with this ๐Ÿคทโ€โ™‚๏ธ

I've declared a new type like this:

@newtype final case class Id(value: String)
@newtype final case class ExternalId(value: String)

Later in the code I finish up with a map mapping: Map[Id, ExternalId]. But when I need to collect it's keys/values to an array I get compilation errors:

val myIds = mapping.keys.toArray
val externalIds = mapping.values.toArray

Error:

No ClassTag available for ...Id
No ClassTag available for ...ExternalId

How is this supposed to be handled. Are newtypes incompatible with arrays because of generics?

Prevent unsafe type ascription

The current encoding allows for some unsafe type ascriptions. While this would basically never happen in a real world scenario, we should still look into improving the encoding.

Here's an example of the problem. I've abridged the debug output for simplicity.

scala> @newtype(debug = true) case class Foo(x: String)
Expanded @newtype Foo:
{
  type Foo = Foo.Type;
  abstract trait Foo$Types extends scala.AnyRef {
    type Repr = String;
    type Base = _root_.scala.Any { type Foo$newtype };
    abstract trait Tag extends _root_.scala.Any;
    type Type <: Base with Tag
  };
  object Foo extends scala.AnyRef with Foo$Types { .. }
}
defined type alias Foo
defined trait Foo$Types
defined object Foo

scala> Foo("a"): Foo.Tag
java.lang.ClassCastException: java.lang.String cannot be cast to Foo$Types$Tag

The main reason for the Tag trait is to anchor the companion so it's in the implicit search path. I've been experimenting with refinements to see if that could help but so far I've been unable to get implicit resolution working without it.

More Documentation

Sorry, this isn't an issue as such, I was just looking for more information on how newtype works. The README says something like this is generated:

package object types {
  type WidgetId = WidgetId.Type
  object WidgetId {
    type Repr = Int
    type Base = { type WidgetId$newtype }
    trait Tag
    type Type <: Base with Tag

    def apply(x: Int): WidgetId = x.asInstanceOf[WidgetId]

    implicit final class Ops$newtype(val $this$: Type) extends AnyVal {
      def toInt: Int = $this$.asInstanceOf[Int]
    }
  }
}

I get the basic idea that you use macros to generate a value class but I wasn't sure why so many intermediate types are defined or what type Base = { type WidgetId$newtype }, which looks abstract, did?

Any more info would be much appreciated, thanks!!!

Support for private constructors (via private `Coercible` instances)

The Coercible instances currently generated by the @newtype macro are always publicly available in implicit scope. I think this makes sense when defining a newtype as a case class since a standard apply method will be generated, but when defining one as a class with a custom apply method, it allows external code to bypass any validation logic in that method. For example

// types.scala
package object types {
  @newtype class PositiveInt(i: Int)
  object PositiveInt {
    def apply(i: Int): Option[PositiveInt] = if (i > 0) Some(i.coerce[PositiveInt]) else None
  }
}

// test.scala -- this compiles but ideally it wouldn't
-1.coerce[types.PositiveInt]

Would it be possible to make the Coercible instances for a class only visible in implicit scope in the companion object? Or if that seems like too broad of a change, perhaps the logic could only apply when the class constructor is explicitly marked as private, e.g. @newtype class PositiveInt private (i: Int)?

Thank you for all your work on this library!

Warning emitted when using @newtype in package object

I have the following code:

package object stuff {
  @newtype case class Thing(underlying: Int)
}

In scala 2.12.x the following warning is issued (making -Xfatal-warning impossible):

[warn] package.scala:10: it is not recommended to define classes/objects inside of package objects.
[warn] If possible, define trait MetricActorRef__Types in package metrics instead.
[warn]   @newtype case class MetricActorRef(underlying: ActorRef)
[warn]    ^

This warning happens if I use any scala-newtype version > 0.2.1 (that's the last version that works without the warning).

I am able to work around the issue by using https://github.com/ghik/silencer with the pathFilters pointing to the file in question (the @silent annotation does not work).

Existing classes are shadowed by type aliases inside the object

Example:

case class Type(name: String)

@newtype case class Foo(value: List[Type])

val value: List[Type] = List(Type("abc"))
Foo(value)

The code does not compile due to the following error:

type mismatch;
 found   : List[Type]
 required: List[Foo.Type]

The simplest solution is to rename all type aliases to avoid the possibility of name collision (like prefixing them with $).

type $Base = ...
type $Repr = ...
type $Type = ...
type $Tag = ...

Currently, as a workaround, the user can create an alias (if changing the name isn't an option), and the code would work as expected:

type TType = Type
@newtype case class Foo(value: List[TType])

Advantages over AnyVal?

The README.md compares this library to Haskell's newtype and to Tagged types. However, more crucially, it doesn't mention how this is any different/better than simply using case class Thing(value: String) extends AnyVal.

From my understand this is an alternative to extends AnyVal, hence this info is crucial.

Feature Request: match case and isInstanceOf

it would be awesom if the NewType and NewSubType would also behave respectively when applied to isInstanceOf[_] and case _:Type =>

while a NewType is indeed not recognized for function arguments

import io.estatico.newtype.NewType

object Point extends NewType.Default[(Int, Int)]
val p = Point((1,2))

def add(t:(Int, Int)): Int = t._1 + t._2
add(p)  // will raise an error

The following does not work as hoped for

p.isInstanceOf[(_, _)]  // returns <true>, however we would like to have <false>
p match {
  case p: (_, _) => "bad"
  case _ => "good"
}  // returns "bad"

Is this an underlying systematic issue or can this be adapted to fit the NewType / NewSubType distinction?

Type Roles

Currently, for newtypes we generate a Coercible[O, N] instance where O is the original type and N is the newtype. While this is perfectly fine, we go a step further and generate a Coercible[F[O], F[N]] instance for any F[_]. This is where we get into trouble. There are cases where this shouldn't be permitted due to the nature of the data structure we're dealing with. For example, let's look at how this would work with dogs.Set which relies on an implicit Order instance for its operations -

import cats.instances.int._
import cats.Order
import io.estatico.newtype.ops._
import io.estatico.newtype.macros.newtype

// Like Int except ordered in reverse.
@newtype case class RevInt(value: Int)
object RevInt {
  implicit val order: Order[RevInt] =
    Order.from((x, y) => -Order[Int].compare(x.value, y.value))
}

// Build a dogs.Set[Int]
println(dogs.Set(1, 2, 3))
// Set(1,2,3)

// Build a dogs.Set[RevInt]
println(dogs.Set(RevInt(1), RevInt(2), RevInt(3)))
// Set(3,2,1)

// Build a dogs.Set[Int], coerce it to dogs.Set[RevInt], and add an element
println(dogs.Set(1, 2).coerce[dogs.Set[RevInt]] + RevInt(3))
// Set(3,1,2)

One quick and dirty way to deal with this would be to introduce type roles via a type class.

trait TypeRole[A] {
  type Role
}

object TypeRole {

  def mk[A, R]: TypeRole[A] { type Role = R } =
    _instance.asInstanceOf[TypeRole[A] { type Role = R }]

  private val _instance = new TypeRole[Nothing] {}

  type Nominal[A] = TypeRole[A] { type Role = types.Nominal }
  type Representational[A] = TypeRole[A] { type Role = types.Representational }

  object types {
    sealed trait Representational
    sealed trait Nominal
  }
}

Then we'd define this Coercible instance based on the type role -

implicit def reprF[F[_], A, B](
  implicit ev: TypeRole.Representational[F[A]]
): Coercible[F[A], F[B]] = Coercible.unsafe

We then need to define type role instances -

implicit def typeRoleScalaSet[A]: TypeRole.Representational[Set[A]] = TypeRole.mk

implicit def typeRoleDogSet[A]: TypeRole.Nominal[Set[A]] = TypeRole.mk

// Compiles
println(Set(1, 2, 3).coerce[Set[RevInt]])
// Set(1, 2, 3)

// Does not compile now
println(dogs.Set(1, 2, 3).coerce[dogs.Set[RevInt]])

See -

using the newtype in the companion

I'd like to do something like the following, which is a fully compilable version of http://degoes.net/articles/effects-without-transformers

But if I change the value class encoding for @newtype, I get a compile error

[error] stateio.scala:23:49: class type required but stateio.FastState.StateTask.Type[A] found
[error]               def from[X](fa: Task[X])    = new StateTask(fa)
[error]                                                 ^
import scalaz._, Scalaz._, ioeffect._
import Isomorphism._
import io.estatico.newtype.macros.newtype

object FastState extends SafeApp {
  final class StateTask[A](val io: Task[A]) extends AnyVal
  object StateTask {

    def create[S](initial: S): Task[MonadState[StateTask, S]] =
      for {
        ref <- IORef(initial)
      } yield
        new MonadState[StateTask, S] with IsomorphismMonad[StateTask, Task] {
          override val G: Monad[Task] = Monad[Task]
          override val iso: StateTask <~> Task =
            new IsoFunctorTemplate[StateTask, Task] {
              def to[X](ga: StateTask[X]) = ga.io
              def from[X](fa: Task[X])    = new StateTask(fa)
            }

          override def get: StateTask[S] = new StateTask(ref.read)
          override def put(s: S): StateTask[Unit] =
            new StateTask(ref.write(s))

          override def init = get
        }
  }

  def program[F[_]](implicit F: MonadState[F, Int]): F[String] =
    for {
      orig   <- F.get
      update = orig + 10
      _      <- F.put(update)
    } yield update.toString

  def app: Task[Unit] =
    for {
      stateMonad <- StateTask.create(10)
      output     <- program(stateMonad).io
      _          <- console.putStrLn(output).widenError[Throwable]
    } yield ()

  def run(@unused args: List[String]): IO[Void, ExitStatus] =
    app.attempt.map(_ => ExitStatus.ExitNow(0))
}

@newsubtype instances cannot be used in Arrays

version 0.4.2.

object Test {
  @newsubtype case class VectorPointer(addr: Long)
 }

scala> new Array[Test.VectorPointer](10)
<console>:12: error: cannot find class tag for element type Test.VectorPointer
       new Array[Test.VectorPointer](10)

How to avoid abstract type pattern is unchecked error?

Given this reproduction:

import io.estatico.newtype.macros.newsubtype

import scala.scalajs.js.|

object Main extends App {

  @newsubtype final case class Foo[A](unwrap: A)

  @newsubtype final case class Bar[A](unwrap: A)

  def which[A, B](fooOrBar: Foo[A] | Bar[B]) = fooOrBar match {
    case _: Foo[_] => "foo"
    case _: Bar[_] => "bar"
  }
}

How can I avoid this error?

[error] /Users/jason/src/bug-reports/src/main/scala/Main.scala:12:13: abstract type pattern Main.Foo.Type[_] (the underlying of Main.Foo[_]) is unchecked since it is eliminated by erasure
[error]     case _: Foo[_] => "foo"
[error]             ^

Normally in Scala.js we would have to ascribe it as Any to do the match but that doesn't seem necessary here for whatever reason. IntelliJ at least still thinks that this is a fruitless type test so the Any ascription could be cleaner.

I was thinking maybe it has something to do with this comment in #18 although I'm not quite seeing the implications:

Note that when matching on Any compiler warnings will be emitted, so I think that should be enough to clue in users that they're being unsafe.

Is there a workaround, even if it is unsafe?

recursive coerce

I often wrap newtypes in newtypes and then I want to access the basetype. Example:

@newtype case class Secret(value: String)
@newtype case class Password(value: Secret)
@newtype case class AdminPassword(value: Password)

val adminPassword: AdminPassword = ???

// Access the basetype
println(adminPassword.value.value.value)

Something like adminPassword.coerce[String] would be nice, or maybe even adminPassword.underlying. As Coercible is a typeclass, I think with the correct derivation it should be possible to get something like it.

Opinions?

No TypeTag available for newtypes

Currently, there is no way to get a TypeTag for a newtype:

@newtype case class WidgetId(toInt: Int)

val widgetId = WidgetId(5)

import scala.reflect.runtime.universe._

val tt = typeTag[WidgetId] // failed with No TypeTag available

WeakTypeTag works fine:

val wtt = weakTypeTag[WidgetId]

Also, I can get a TypeTag for the Repr type:

val repr = typeTag[WidgetId.Repr]

Looks like there is no way to get a TypeTag for the newtype in the current newtype encoding because newtype's type is abstract, but TypeTag can be summoned only for a concrete type.

About my use case: I'm using doobie and it uses TypeTags very extensively for better logging and error reporting.

Derive typeclasses via Coercible hurts compiler performance?

Since the introduction of newtypes in conjuction with refined I see a big increase in compilation time. Especially in my postgres module. I was using refined before in my postgres module, but not with newtypes. I'm using doobie and SQL/fragment interpolated strings to construct queries. The string interpolator of doobie summons foreach interpolated variable a Put type class (which is used to convert the variable being interpolated to a JDBC data type).

Here's the code to convert newtypes to Put and Get (for reading data from JDBC)

  implicit def coerciblePut[N, P](implicit ev: Coercible[Put[P], Put[N]], R: Put[P]): Put[N] = ev(R)
  implicit def coercibleGet[N, P](implicit ev: Coercible[Get[P], Get[N]], R: Get[P]): Get[N] = ev(R)

I've included the scalac-profiling aswell: https://gist.github.com/Fristi/363e7fcf8f899e24eae53d42d741fd13

It seems to not have repeeated expansions, but rather unique expansions

Warning when using @newtype in package object

I have the following code:

package object stuff {
  @newtype case class Thing(underlying: Int)
}

In scala 2.12.x the following warning is issued (making -Xfatal-warning impossible):

[warn] package.scala:10: it is not recommended to define classes/objects inside of package objects.
[warn] If possible, define trait MetricActorRef__Types in package metrics instead.
[warn]   @newtype case class MetricActorRef(underlying: ActorRef)
[warn]    ^

This warning happens if I use any scala-newtype version > 0.2.1 (that's the last version that works without the warning).

I am able to work around the issue by using https://github.com/ghik/silencer with the pathFilters pointing to the file in question (the @silent annotation does not work).

Evaluate the possibility of not generating Coercible instances

There are use cases when the generation of the Coercible instances is not required. One example might be when using @newtype annotation in the internal implementation of a library without bringing a runtime dependency on the Coercible type to the users of the latter. A possible way could be to add another flag like the ones in here to drive select this behaviour. Something like coercible: Boolean = true. Thanks.

Avoid defining names which easily clash

This doesn't compile due to the use of T as a type param in the generated deriving method -

@newtype case class CanDerive[F[_], R, T](value: F[T])

Generates this method -

def deriving[T[_], F[_], R, T](implicit ev: T[Repr[F, R, T]]): T[Type[F, R, T]] = ev.asInstanceOf[T[Type[F, R, T]]]

We should go through the methods and make sure we use unique names, either by suffixing with $ or using something like c.freshName.

Drop Scala 2.10 support

I'd like to propose the following steps:

  • merge #51
  • cut a new release for all 4 scala version
  • drop support for 2.10 (I'm happy to send a PR fro this one)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.