学习 Scala 3.
我怎样才能让这段代码类型匹配和编译?
trait Key {
type Value
}
object Name extends Key {
type Value = String
}
object Age extends Key {
type Value = Int
}
type DB = (k: Key) => Option[k.Value]
val dbImpl: DB = (k: Key) => {
k match {
case Name => Some("abc") // this does not compile, how can i make it sniff Value type is String automatically?
case Age => None
}
}
谢谢
作为解决方法,您可以尝试匹配类型
trait Key
object Name extends Key
object Age extends Key
type OptValue[K <: Key] = K match
case Name.type => Option[String]
case Age.type => Option[Int]
def dbImpl[K <: Key](k: K): OptValue[K] = k match
case _: Name.type => Some("abc")
case _: Age.type => None
或
val dbImpl: [K <: Key] => K => OptValue[K] =
[K <: Key] => (k: K) => k match
case _: Name.type => Some("abc")
case _: Age.type => None
提醒一下
type DB = [K <: Key] => K => OptValue[K]
val dbImpl: DB = [K <: Key] => (k: K) => k match
case _: Name.type => Some("abc")
case _: Age.type => None
或
def dbImpl[K <: Key](k: K): OptValue[K] = k match
case Name => Some("abc")
case Age => None
或
type Value[K <: Key] = K match
case Name.type => String
case Age.type => Int
def dbImpl[K <: Key](k: K): Option[Value[K]] = k match
case _: Name.type => Some("abc")
case _: Age.type => None
不会工作。
Another option is type classes
trait Key
object Name extends Key
object Age extends Key
// type class
trait KeyValue[K <: Key]:
type Value
type Out = Option[Value]
def apply(k: K): Out
object KeyValue:
type Aux[K <: Key, V] = KeyValue[K] { type Value = V }
def instance[K <: Key, V](f: K => Option[V]): Aux[K, V] = new KeyValue[K]:
override type Value = V
override def apply(k: K): Out = f(k)
given Aux[Name.type, String] = instance(_ => Some("abc"))
given Aux[Age.type, Int] = instance(_ => None)
def dbImpl[K <: Key](k: K)(using kv: KeyValue[K]): kv.Out = kv(k)
另一个选择是内联并使用
scala.compiletime.summonFrom
trait Key:
type Value
object Name extends Key:
override type Value = String
object Age extends Key:
override type Value = Int
inline def dbImpl(k: Key): Option[k.Value] = inline k match
case Name => summonFrom {
case _: (String =:= k.Value) => Some("abc")
}
case Age => summonFrom {
case _: (Option[Int] =:= Option[k.Value]) => None: Option[Int]
}
最简单的方法是让
Value
成为类型参数而不是类型成员
trait Key[Value]
object Name extends Key[String]
object Age extends Key[Int]
def dbImpl[V](k: Key[V]): Option[V] = k match
case Name => Some("abc")
case Age => None
此实现编译时
trait Key:
type Value
object Name extends Key:
override type Value = String
object Age extends Key:
override type Value = Int
def dbImpl[V](k: Key {type Value = V}): Option[V] = k match
case Name => Some("abc")
case Age => None
或
trait Key:
type Value
object Key:
type Aux[V] = Key { type Value = V }
object Name extends Key:
override type Value = String
object Age extends Key:
override type Value = Int
def dbImpl[V](k: Key.Aux[V]): Option[V] = k match
case Name => Some("abc")
case Age => None
或
trait Key:
type Value
object Name extends Key:
override type Value = String
object Age extends Key:
override type Value = Int
def dbImpl(k: Key): Option[k.Value] = k match
case Name => Some("abc")
case Age => None
没有。 (Scala 3.2.2)
Aleksander Boruch-Gruszecki。 Dotty 中的 GADT https://www.youtube.com/watch?v=VV9lPg3fNl8
戴尔维南德。用于模式匹配的空间引擎https://www.youtube.com/watch?v=yaxJPIsy4Js