gpt4 book ai didi

scala - 获取 "most specific"输入类型

转载 作者:行者123 更新时间:2023-12-04 17:54:39 26 4
gpt4 key购买 nike

假设我有一个类似函数的类型,例如

trait Parser[-Context, +Out]

我希望能够组合多个解析器,这样组合的 Context 将成为组合解析器上下文中最具体的类型。例如:

Parser[Any, Int] + Parser[String, Long] = Parser[String, (Int, Long)]
Parser[String, Int] + Parser[Any, Long] = Parser[String, (Int, Long)]
Parser[Option[Int], Foo] + Parser[Some[Int], Bar] = Parser[Some[Int], (Foo, Bar)]
Parser[String, Foo] + Parser[Int, Bar] = <should be a compile error>

为了更具体地说明这个例子,假设我有一个像这样的函数组合器

def zipFuncs[A, B1, B2](f1: A => B1, f2: A => B2): A => (B1, B2) = {
a => (f1(a), f2(a))
}

还有一些功能比如

val f1 = { a: Any => 123 }
val f2 = { a: String => 123 }
val f3 = { a: Option[Int] => 123 }

现在我可以做

> zipFuncs(f1, f2)
res1: String => (Int, Int) = <function>

> zipFuncs(f1, f3)
res2: Option[Int] => (Int, Int) = <function>

> zipFuncs(f2, f3)
res3: Option[Int] with String => (Int, Int) = <function1>

但我想要的是 zipFuncs(f2, f3) 根本不编译。由于 String 不是 Option[Int] 的子类型,并且 Option[Int] 也不是 String 的子类型>,无法为 res3 构造输入值。

我确实创建了一个类型类:

// this says type `T` is the most specific type between `T1` and `T2`
sealed trait MostSpecificType[T, T1, T2] extends (T => (T1, T2))
// implementation of `object MostSpecificType` omitted

def zipFuncs[A, A1, A2, B1, B2](f1: A1 => B1, f2: A2 => B2)(
implicit mst: MostSpecificType[A, A1, A2]
): A => (B1, B2) = { a: A =>
val (a1, a2) = mst(a)
f1(a1) -> f2(a2)
}

这实现了上述目标,但有一个非常烦人的问题。 IntelliJ 会将有效组合突出显示为错误,并推断“最具体的类型 (A)”实际上是 Nothing,而实际上它是一个实数值。 Here's the actual issue in practice .

突出显示问题肯定是 IntelliJ 中的错误,谷歌搜索似乎暗示各种重置/缓存删除/等应该修复它(但没有)。不管指责如何,我都希望找到一种既能满足我最初的要求又不会混淆 IntelliJ 的替代方法。

最佳答案

您可以使用 generalized type constraints 来实现:

def zipFuncs[A1, A2, B1, B2](f1: A1 => B1, f2: A2 => B2)
(implicit ev: A2 <:< A1): A2 => (B1, B2) = {
a => (f1(a), f2(a))
}

val f1 = { a: Any => 123 }
val f2 = { a: String => 123 }
val f3 = { a: Option[Int] => 123 }

zipFuncs(f1, f2) // works
zipFuncs(f1, f3) // works
zipFuncs(f2, f3) // cannot prove that Option[Int] <:< String

但是,这要求第二个函数在输入参数中使用比第一个函数更具体的类型。这没关系,除非您还希望 zipFuncs(f2, f1) 也能工作。如果你确实有这个要求,我认为除了做一些implicit type gymnastics之外别无他法。类似于你已经做过的。

编辑:请参阅 Eduardo 的回答以了解实现此目的的巧妙技巧。

是的,我也遇到过很多情况,IntelliJ 将某事视为错误,而实际上并非如此。我知道这很乏味,但除了报告问题和等待之外,我看不到解决问题的方法。

关于scala - 获取 "most specific"输入类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40875161/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com