Reputation: 41909
Looking at the Akka docs for creating an Actor:
The recommended approach to create the actor Props is not supported for cases when the actor constructor takes value classes as arguments.
Is it possible to define a function:
def anyTypeButValueClass[A : ...](x: A) = ???
where A
is any type except for a value class at compile-time?
My understanding is that value classes extend AnyVal
,(per docs) but there's also:
The standard implementation includes nine AnyVal subtypes:
Double, Float, Long, Int, Char, Short, and Byte
are the numeric value types.
Unit and Boolean
are the non-numeric value types.
per AnyVal.
How can this function be written?
Upvotes: 1
Views: 1199
Reputation: 108091
If you're willing to use a library like shapeless, you could also encode it like
import shapeless._
def anyTypeButValueClass[A: |¬|[AnyVal]#λ](x: A) = x
ref: https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/package.scala#L54
example:
@ def anyTypeButValueClass[A: |¬|[AnyVal]#λ](x: A) = x
defined function anyTypeButValueClass
@ anyTypeButValueClass(42)
Compilation Failed
Main.scala:296: ambiguous implicit values:
both method nsubAmbig1 in package shapeless of type [A, B >: A]=> shapeless.<:!<[A,B]
and method nsubAmbig2 in package shapeless of type [A, B >: A]=> shapeless.<:!<[A,B]
match expected type shapeless.<:!<[Int,AnyVal]
anyTypeButValueClass(42)
^
@ anyTypeButValueClass("foo")
res0: String = "foo"
Upvotes: 1
Reputation: 144126
The Scala type hierarchy shows that Any
has two direct subtypes, AnyRef
and AnyVal
for reference and value types respectively.
This means you can just add an AnyRef
constraint:
def anyTypeButValueClass[A <: AnyRef](x: A) = ???
Upvotes: 6
Reputation: 170713
"Accept any type but AnyVal
" is answered at Enforce type difference, but it's very different from "Accept any type which doesn't extend AnyVal
", which is again different from "Accept any type except for a value class". Value classes do extend AnyVal
, but so do the primitive types.
You can do it in this way:
// just a marker trait
sealed trait NotAValueClass[A]
object NotAValueClass {
implicit def AnyRefIsNotAValueClass[A <: AnyRef]: NotAValueClass[A] = new NotAValueClass[A] {}
implicit val IntIsNotAValueClass: NotAValueClass[Int] = new NotAValueClass[Int] {}
... // same for other primitive types
}
def anyTypeButValueClass[A : NotAValueClass](x: A) = ...
Upvotes: 2