You can build inline structure types:
scala> val a = new {def hello = null} -> 1 // by the way hello is accessible in a (but scala uses reflection for that) a: (AnyRef{def hello: Null}, Int) = ( $anon$1@68e2da47 ,1) scala> var b = new {def hello = null} -> 2 b: (AnyRef{def hello: Null}, Int) = ( $anon$1@77147ad6 ,2) scala> b = a b: (AnyRef{def hello: Null}, Int) = ( $anon$1@68e2da47 ,1) scala> var c = new {def helloooo = null} -> 1 c: (AnyRef{def helloooo: Null}, Int) = ( $anon$1@38def4a2 ,1) scala> c = a <console>:15: error: type mismatch; found : (AnyRef{def hello: Null}, Int) required: (AnyRef{def helloooo: Null}, Int) c = a ^
So, you can combine them with objects to give them unique types:
new {def myTypeName = null} -> myObject
Or (a little slower beacause of reflection)
scala> def mlp( x: ({def obj: Symbol}, Int)) = x._1.obj -> x._2 warning: there were 1 feature warning(s); re-run with -feature for details mlp: (x: (AnyRef{def obj: Symbol}, Int))(Symbol, Int) scala> mlp(new { def a1 = null; def obj = 'a1 } -> 1) res18: (Symbol, Int) = ('a1,1) scala> mlp(new { def a2 = null; def obj = 'a2 } -> 1) res19: (Symbol, Int) = ('a2,1)
You can combine it with tags to annotate your type, for example:
import scalaz._ import Scalaz._ scala> def markALittle[T](a: T) = Tag[T, MyLittleType](a) markALittle: [T](a: T) scalaz.@ @[T,MyLittleType] scala> markALittle(new {def hello: Aaa = null}) res15: scalaz.@ @[AnyRef{def hello: Aaa},MyLittleType] = $anon$1@a8c48e8
Additional tag examples:
scala> trait MyLittleType scala> trait Spike extends MyLittleType; val x = Tag[Symbol, Spike]('k1) -> 1 x: ( scalaz.@ @[Symbol,Spike], Int) = ('k1,1) scala> trait Rainbow extends MyLittleType; val y = Tag[Symbol, Rainbow]('k2) -> 1 y: ( scalaz.@ @[Symbol,Rainbow], Int) = ('k2,1) scala> val y: ( scalaz.@ @[Symbol,Spike], Int) = Tag[Symbol, Rainbow]('k1) -> 1 <console>:22: error: type mismatch; found : ( scalaz.@ @[Symbol,Rainbow], Int) required: ( scalaz.@ @[Symbol,Spike], Int) val y: ( scalaz.@ @[Symbol,Spike], Int) = Tag[Symbol, Rainbow]('k1) -> 1 scala> val z: ( scalaz.@ @[Symbol,_ <: MyLittleType], Int) = Tag[Symbol, Rainbow]('k1) -> 1 z: ( scalaz.@ @[Symbol, _ <: MyLittleType], Int) = ('k1,1)
So you can:
scala> def mlt[T <: MyLittleType](x :( scalaz.@ @[Symbol,T], Int)) = x mlt: [T <: MyLittleType](x: ( scalaz.@ @[Symbol,T], Int))( scalaz.@ @[Symbol,T], Int) scala> mlt(x) res42: ( scalaz.@ @[Symbol,Spike], Int) = ('k1,1) scala> mlt(y) res43: ( scalaz.@ @[Symbol,Rainbow], Int) = ('k2,1)
Or just use:
scala> val x = Tag[Int, Rainbow](1) x: scalaz.@ @[Int,Rainbow] = 1 scala> val y = Tag[Int, Spike](1) y: scalaz.@ @[Int,Spike] = 1
You can use x as Int with Tag.unwrap(x) or just define implicit def t[T] = Tag.unwrap[Int, T] _ so that there is no difference between a tag and Int, but be careful: any function, not tag-oriented, remove the tag)
Other built-in constructor solutions:
a) ugly
scala> class ___ defined class ___ scala> class __[T,U] extends ___ defined class __ scala> val x = Tag[Symbol, ___ __ ___]('k1) -> 1 x: ( scalaz.@ @[Symbol,__[___,___]], Int) = ('k1,1) scala> var y = Tag[Symbol, ___ __ ___ __ ___]('k1) -> 1 y: ( scalaz.@ @[Symbol,__[__[___,___],___]], Int) = ('k1,1) scala> y = x <console>:59: error: type mismatch; found : ( scalaz.@ @[Symbol,__[___,___]], Int) required: ( scalaz.@ @[Symbol,__[__[___,___],___]], Int) y = x ^ scala> def mlp[X <: scalaz.@ @[Symbol, _]](x: (X, Int)) = x mlp: [X <: scalaz.@ @[Symbol, _]](x: (X, Int))(X, Int) scala> mlp(x) res106: ( scalaz.@ @[Symbol,__[___,___]], Int) = ('k1,1)
b) funny:
class - [B <: -[_, _], A <: symbolic[A]] (a: A, b: B) { def -[T <: symbolic[T]](c: T) = new - (c, this) } trait symbolic[F <: symbolic[F]] { def - [T <: symbolic[T]](b: T) = new - [single[F],T](b, new single(this.asInstanceOf[F])) } class single[T <: symbolic[T]](a: T) extends - [single[_],T](a, null) val a = new a_; class a_ extends symbolic[a_] val b = new b_; class b_ extends symbolic[b_] val c = new c_; class c_ extends symbolic[c_] ... scala> val x = hello -> 1 x: (-[o_,-[l_,-[l_,-[h_,end[e_]]]]], Int) = ( $minus@350bc88 ,1) scala> var y = helloo -> 2 y: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) = ( $minus@46d7fdc0 ,2) scala> y = x <console>:13: error: type mismatch; found : (-[o_,-[l_,-[l_,-[h_,end[e_]]]]], Int) required: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) y = x ^ scala> var z = helloo -> 2 z: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) = ( $minus@6b899d5d ,2) scala> z = y z: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) = ( $minus@46d7fdc0 ,2)