用于元组的 Scala 3 类型绑定`<:<` 技巧

问题描述

在线会议期间,Adam Warski 展示了一个技巧来证明元组具有特定结构:

一个实现是

    def sequence[T <: Tuple](t: T): Option[InverseMap[T,Option]] =
        val unwrapped = t.productIterator.collect { case Some(v) => v}.toArray[Any]
        if unwrapped.length == t.productArity then Some(Tuple.fromArray(unwrapped).asInstanceOf[InverseMap[T,Option]])
        else None

允许(但不应该)

sequence(("x",true)) // compiles

并用技巧实现

def betterSequence[T <: Tuple](t: T)(using T <:< Map[InverseMap[T,Option],Option]): Option[InverseMap[T,Option]] =
    val unwrapped = t.productIterator.collect { case Some(v) => v}.toArray[Any]
    if unwrapped.length == t.productArity then Some(Tuple.fromArray(unwrapped).asInstanceOf[InverseMap[T,Option]])
    else None
betterSequence(("x",true)) // compile error

能解释一下吗

(using T <:< Map[InverseMap[T,Option])

有效以及为什么 TMap 的子类型?

解决方法

InverseMap[T,Foo] 接受一个看起来像 T 的元组 (Foo[t1],Foo[t2],...,Foo[tn]) 并将它变成一个元组 (t1,t2,tn)。如果 T 没有那个结构,即它不是一堆 Foo,它不会编译(有一个有点神秘的错误)。这是证明元组中只有 Option 的主要因素。

下一个问题是如何将这个类型插入到 betterSequence 方法中。 Map[T,Foo] 将看起来像 T 的元组 (t1,tn) 变成 (Foo[t1],Foo[tn])InverseMap 的倒数)。因此,Map[InverseMap[T,Option],Option] 只是 T(想想数学,其中 f(f^-1(x)) 又是 x。边界 T <:< T 将始终为真,但前提是InverseMap 先成功。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...