您可以構建結構型式直列:
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) = ([email protected],1)
scala> var b = new {def hello = null} -> 2
b: (AnyRef{def hello: Null}, Int) = ([email protected],2)
scala> b = a
b: (AnyRef{def hello: Null}, Int) = ([email protected],1)
scala> var c = new {def helloooo = null} -> 1
c: (AnyRef{def helloooo: Null}, Int) = ([email protected],1)
scala> c = a
<console>:15: error: type mismatch;
found : (AnyRef{def hello: Null}, Int)
required: (AnyRef{def helloooo: Null}, Int)
c = a
^
所以,你可以將它們組合使用對象給他們鍵入獨特:
new {def myTypeName = null} -> myObject //now your myObject tagged with 'myTypeName', but your methods should be aware about tuples
def mlp(x: ((Any, YourObjectsType), Int)) = x
或(東陽反射的稍微慢一點)
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)
你可以用tags結合起來來註釋類型,如:
import scalaz._
import Scalaz._
scala> def markALittle[T](a: T) = Tag[T, MyLittleType](a)
markALittle: [T](a: T)[email protected]@[T,MyLittleType]
scala> markALittle(new {def hello: Aaa = null})
res15: [email protected]@[AnyRef{def hello: Aaa},MyLittleType] = [email protected]
更多標籤例子:
scala> trait MyLittleType
scala> trait Spike extends MyLittleType; val x = Tag[Symbol, Spike]('k1) -> 1
x: ([email protected]@[Symbol,Spike], Int) = ('k1,1)
scala> trait Rainbow extends MyLittleType; val y = Tag[Symbol, Rainbow]('k2) -> 1
y: ([email protected]@[Symbol,Rainbow], Int) = ('k2,1)
scala> val y: ([email protected]@[Symbol,Spike], Int) = Tag[Symbol, Rainbow]('k1) -> 1
<console>:22: error: type mismatch;
found : ([email protected]@[Symbol,Rainbow], Int)
required: ([email protected]@[Symbol,Spike], Int)
val y: ([email protected]@[Symbol,Spike], Int) = Tag[Symbol, Rainbow]('k1) -> 1
scala> val z: ([email protected]@[Symbol,_ <: MyLittleType], Int) = Tag[Symbol, Rainbow]('k1) -> 1
z: ([email protected]@[Symbol, _ <: MyLittleType], Int) = ('k1,1)
所以,你可以:
scala> def mlt[T <: MyLittleType](x :([email protected]@[Symbol,T], Int)) = x
mlt: [T <: MyLittleType](x: ([email protected]@[Symbol,T], Int))([email protected]@[Symbol,T], Int)
scala> mlt(x)
res42: ([email protected]@[Symbol,Spike], Int) = ('k1,1)
scala> mlt(y)
res43: ([email protected]@[Symbol,Rainbow], Int) = ('k2,1)
或者只需使用:
scala> val x = Tag[Int, Rainbow](1)
x: [email protected]@[Int,Rainbow] = 1
scala> val y = Tag[Int, Spike](1)
y: [email protected]@[Int,Spike] = 1
您可以操作x
如同時使用Int
Tag.unwrap(x)
,或只是定義implicit def t[T] = Tag.unwrap[Int, T] _
,使標籤和Int之間沒有什麼區別,但要小心在這裏 - 任何非標籤導向功能將刪除標記)
另一線上型構造解決方案:
一)醜
scala> class ___
defined class ___
scala> class __[T,U] extends ___
defined class __
scala> val x = Tag[Symbol, ___ __ ___]('k1) -> 1
x: ([email protected]@[Symbol,__[___,___]], Int) = ('k1,1)
scala> var y = Tag[Symbol, ___ __ ___ __ ___]('k1) -> 1
y: ([email protected]@[Symbol,__[__[___,___],___]], Int) = ('k1,1)
scala> y = x
<console>:59: error: type mismatch;
found : ([email protected]@[Symbol,__[___,___]], Int)
required: ([email protected]@[Symbol,__[__[___,___],___]], Int)
y = x
^
scala> def mlp[X <: [email protected]@[Symbol, _]](x: (X, Int)) = x
mlp: [X <: [email protected]@[Symbol, _]](x: (X, Int))(X, Int)
scala> mlp(x)
res106: ([email protected]@[Symbol,__[___,___]], Int) = ('k1,1)
二)搞笑:
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 = h-e-l-l-o -> 1
x: (-[o_,-[l_,-[l_,-[h_,end[e_]]]]], Int) = ([email protected],1)
scala> var y = h-e-l-l-o-o -> 2
y: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) = ([email protected],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 = h-e-l-l-o-o -> 2
z: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) = ([email protected],2)
scala> z = y
z: (-[o_,-[o_,-[l_,-[l_,-[h_,end[e_]]]]]], Int) = ([email protected],2)
我想你想要的東西像[基於字面值的單例類型](http://docs.scala-lang.org/sips/pending/42.type.html)。 – 2014-12-03 14:48:33
Scala編譯器的[Typelevel's fork](https://github.com/typelevel/scala)中提供了IIRC。 – 2014-12-03 14:54:14
或者,[形狀記錄](https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#extensible-records)你想要什麼? – lmm 2014-12-03 16:05:08