为 Scala 中的类型别名提供隐式证据
Provide implicit evidence for a type alias in Scala
有没有办法让编译器在寻找隐含证据时以某种方式考虑类型别名?
这是我试图解决的问题示例:
// Third party library
class Foo[T, P]
class FooOps[FTP, T] {
def apply[F[_, _], P](t: T)(implicit ev: F[T, P] =:= FTP): FTP = ???
}
type StringFoo = Foo[String, Boolean]
object StringFoo extends FooOps[StringFoo, String]
StringFoo("hello")
// Attempt to wrap the third party type but have the same ops
class WrappedFoo[FTP](val foo: FTP)
object WrappedFoo {
type F[T, P] = WrappedFoo[Foo[T, P]]
}
type WrappedStringFoo = WrappedFoo[StringFoo]
object WrappedStringFoo extends FooOps[WrappedStringFoo, String]
WrappedStringFoo("hello") // Cannot prove that F[String, P] =:= WrappedStringFoo
WrappedStringFoo[WrappedFoo.F, Boolean]("hello”) // This works
我不太明白编译器是如何推断类型的:
StringFoo("hello")
它是否以某种方式使用可用的隐式来为 F[_, _]
选择一个值?我一直认为它必须先计算出类型。
但是它适用于 StringFoo
但不适用于 WrappedStringFoo
。可能是因为类型参数的数量不同。
如何获得:
WrappedStringFoo("hello")
在不显式指定类型的情况下进行编译?
尝试向范围添加必要的隐式:
import scala.language.higherKinds
class Foo[T, P]
class FooOps[FTP, T] {
def apply[F[_, _], P](t: T)(implicit ev: F[T, P] =:= FTP): FTP = ???
}
type StringFoo = Foo[String, Boolean]
object StringFoo extends FooOps[StringFoo, String]
class WrappedFoo[FTP](val foo: FTP)
object WrappedFoo {
type F[T, P] = WrappedFoo[Foo[T, P]]
//implicit val ev0: WrappedFoo.F[String, Boolean] =:= WrappedStringFoo = ???
implicit val ev0: WrappedFoo.F[String, Boolean] =:= WrappedStringFoo =
null.asInstanceOf[WrappedFoo.F[String, Boolean] =:= WrappedStringFoo]
}
type WrappedStringFoo = WrappedFoo[StringFoo]
object WrappedStringFoo extends FooOps[WrappedStringFoo, String]
WrappedStringFoo("hello")
当您执行 StringFoo("hello")
时,编译器会求解方程 F[String, P] = Foo[String, Boolean]
,它足够聪明地推导出 P = Boolean
、F = Foo
。但是,当您执行 WrappedStringFoo("hello")
时,编译器必须求解方程 F[String, P] = WrappedFoo[Foo[String, Boolean]]
,并且它使用的算法不够智能,无法推断出 P = Boolean
、F = ({ type λ[A, B] = WrappedFoo[Foo[A, B]] })#λ
,即 WrappedFoo.F
(可能还有这样的如果方程式足够先进,则一般无法求解)。所以你应该提供一个提示。明确指定类型参数或提供必要的隐含证据。
解析隐式和类型推断相互影响。您可以阅读 Eugene Burmako 的 thesis.
的第 4.4.3 节
有没有办法让编译器在寻找隐含证据时以某种方式考虑类型别名?
这是我试图解决的问题示例:
// Third party library
class Foo[T, P]
class FooOps[FTP, T] {
def apply[F[_, _], P](t: T)(implicit ev: F[T, P] =:= FTP): FTP = ???
}
type StringFoo = Foo[String, Boolean]
object StringFoo extends FooOps[StringFoo, String]
StringFoo("hello")
// Attempt to wrap the third party type but have the same ops
class WrappedFoo[FTP](val foo: FTP)
object WrappedFoo {
type F[T, P] = WrappedFoo[Foo[T, P]]
}
type WrappedStringFoo = WrappedFoo[StringFoo]
object WrappedStringFoo extends FooOps[WrappedStringFoo, String]
WrappedStringFoo("hello") // Cannot prove that F[String, P] =:= WrappedStringFoo
WrappedStringFoo[WrappedFoo.F, Boolean]("hello”) // This works
我不太明白编译器是如何推断类型的:
StringFoo("hello")
它是否以某种方式使用可用的隐式来为 F[_, _]
选择一个值?我一直认为它必须先计算出类型。
但是它适用于 StringFoo
但不适用于 WrappedStringFoo
。可能是因为类型参数的数量不同。
如何获得:
WrappedStringFoo("hello")
在不显式指定类型的情况下进行编译?
尝试向范围添加必要的隐式:
import scala.language.higherKinds
class Foo[T, P]
class FooOps[FTP, T] {
def apply[F[_, _], P](t: T)(implicit ev: F[T, P] =:= FTP): FTP = ???
}
type StringFoo = Foo[String, Boolean]
object StringFoo extends FooOps[StringFoo, String]
class WrappedFoo[FTP](val foo: FTP)
object WrappedFoo {
type F[T, P] = WrappedFoo[Foo[T, P]]
//implicit val ev0: WrappedFoo.F[String, Boolean] =:= WrappedStringFoo = ???
implicit val ev0: WrappedFoo.F[String, Boolean] =:= WrappedStringFoo =
null.asInstanceOf[WrappedFoo.F[String, Boolean] =:= WrappedStringFoo]
}
type WrappedStringFoo = WrappedFoo[StringFoo]
object WrappedStringFoo extends FooOps[WrappedStringFoo, String]
WrappedStringFoo("hello")
当您执行 StringFoo("hello")
时,编译器会求解方程 F[String, P] = Foo[String, Boolean]
,它足够聪明地推导出 P = Boolean
、F = Foo
。但是,当您执行 WrappedStringFoo("hello")
时,编译器必须求解方程 F[String, P] = WrappedFoo[Foo[String, Boolean]]
,并且它使用的算法不够智能,无法推断出 P = Boolean
、F = ({ type λ[A, B] = WrappedFoo[Foo[A, B]] })#λ
,即 WrappedFoo.F
(可能还有这样的如果方程式足够先进,则一般无法求解)。所以你应该提供一个提示。明确指定类型参数或提供必要的隐含证据。
解析隐式和类型推断相互影响。您可以阅读 Eugene Burmako 的 thesis.
的第 4.4.3 节