1

在在线会话中,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], Option])

有效,为什么T是 的子类型Map

4

1 回答 1

1

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

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

于 2021-01-13T14:14:26.557 回答