scala - Possible to perform pattern match on a generic value with type conforming result? -
scala - Possible to perform pattern match on a generic value with type conforming result? -
is possible perform pattern match result conforms type parameter of outer method? e.g. given:
trait key[a] { def id: int def unapply(k: key[_]): boolean = k.id == id // used fail2 def apply(thunk: => a): = thunk // used fail3 } trait ev[a] { def pull[a1 <: a](key: key[a1]): option[a1] } trait test extends ev[anyref] { val key1 = new key[string] { def id = 1 } val key2 = new key[symbol] { def id = 2 } }
is there implementation of test
(its pull
method) uses pattern match on key
argument , returns option[a1]
each key checked, without utilize of asinstanceof
?
some pathetic tries:
class fails1 extends test { def pull[a1 <: anyref](key: key[a1]): option[a1] = key match { case `key1` => some("hallo") case `key2` => some('welt) } } class fails2 extends test { def pull[a1 <: anyref](key: key[a1]): option[a1] = key match { case key1() => some("hallo") case key2() => some('welt) } } class fails3 extends test { def pull[a1 <: anyref](key: key[a1]): option[a1] = key match { case k @ key1() => some(k("hallo")) case k @ key2() => some(k('welt)) } }
none works, obviously... solution cast:
class ugly extends test { def pull[a1 <: anyref](key: key[a1]): option[a1] = key match { case `key1` => some("hallo".asinstanceof[a1]) case `key2` => some('welt .asinstanceof[a1]) } } val u = new ugly u.pull(u.key1) u.pull(u.key2)
the problem indeed pattern matching ignores erased types. however, there little implicit trickery 1 employ. next preserve type resolution provided match homecoming type.
abstract class unerased[a] implicit case object unerasedstring extends unerased[string] implicit case object unerasedsymbol extends unerased[symbol] class unerasedtest extends test { def pull[ a1 <: anyref ]( key: key[ a1 ])(implicit unerased: unerased[a1]): option[ a1 ] = unerased match { case unerasedstring if key1.id == key.id => some( "hallo" ) case unerasedsymbol if key2.id == key.id => some( 'welt ) case _ => none } } val u = new unerasedtest println( u.pull( u.key1 ) ) println( u.pull( u.key2 ) )
this equivalent defining separate sub classes of key. i find next method preferable may not work if existing code using key[string] can't alter necessary keystring (or much work change).
trait keystring extends key[string] trait keysymbol extends key[symbol] trait test extends ev[ anyref ] { val key1 = new keystring { def id = 1 } val key2 = new keysymbol { def id = 2 } } class subtest extends test { def pull[ a1 <: anyref ]( key: key[ a1 ]): option[ a1 ] = key match { case k: keystring if key1.id == k.id => some( "hallo" ) case k: keysymbol if key2.id == k.id => some( 'welt ) case _ => none } } val s = new subtest println( s.pull( s.key1 ) ) println( s.pull( s.key2 ) )
scala types pattern-matching
Comments
Post a Comment