【问题标题】:Provide implicit evidence for a type alias in Scala为 Scala 中的类型别名提供隐含证据
【发布时间】:2019-02-11 09:04:20
【问题描述】:

有没有办法让编译器在寻找隐含证据时以某种方式考虑类型别名?

这是我试图解决的问题示例:

// 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")

在不明确指定类型的情况下进行编译?

【问题讨论】:

    标签: scala implicit higher-kinded-types


    【解决方案1】:

    尝试在作用域中添加必要的隐式:

    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 = BooleanF = Foo。但是当你这样做 WrappedStringFoo("hello") 时,编译器必须求解方程 F[String, P] = WrappedFoo[Foo[String, Boolean]] 并且它使用的算法不够聪明,无法推断出 P = BooleanF = ({ type λ[A, B] = WrappedFoo[Foo[A, B]] })#λWrappedFoo.F (如果这些方程通常无法求解,则它们足够先进)。所以你应该提供一个提示。要么明确指定类型参数,要么提供必要的隐含证据。

    解析隐式和类型推断会相互影响。您可以阅读 Eugene Burmako 的thesis 的第 4.4.3 节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-18
      • 1970-01-01
      • 2015-08-21
      相关资源
      最近更新 更多