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

Popular posts from this blog

How do I check if an insert was successful with MySQLdb in Python? -

delphi - blogger via idHTTP : error 400 bad request -

postgresql - ERROR: operator is not unique: unknown + unknown -