类型推断和隐式链接

时间:2014-02-21 23:58:17

标签: scala

这是一个简化的例子

我有以下代码:

import scala.language.implicitConversions

trait Mapping[I, O]
trait KeyMapping[K, I, O]

implicit def toMapping[I, O](s: I => O): Mapping[I, O] = ???
implicit def toKeyMapping[K, I, O](s: (K, I => O))(
    implicit ev: (I => O) => Mapping[I, O]): KeyMapping[K, I, O] = ???

def test[K, I, O, M](s: M)(
    implicit ev: M => KeyMapping[K, I, O]
):KeyMapping[K, I, O] = ???

val x = test(1 -> {s:String => true})
            ^

这会出现以下错误:

type mismatch;
found: ((Int, Nothing => Boolean)) => KeyMapping[Int,Nothing,Boolean]
required: ((Int, String => Boolean)) => KeyMapping[Int,Input,Boolean]

为什么会这样?

这可以解决吗?

2 个答案:

答案 0 :(得分:1)

我打算说:

  def test[K, I, O](s: (K, I => O))(
      implicit ev: ((K, I => O)) => KeyMapping[K, I, O]
  ):KeyMapping[K, I, O] = ???

没有M,请注意额外的parens。它将自动尝试应用,但不会尝试。

您可以在2.11(2.10中的-Ytyper-debug)中使用-Yinfer-debug来查看它推断Nothing

函数在输入中是逆变的,因此推断Nothing意味着它为您的I => O采用最宽的类型。您可以进行竞争Mapping次转化,其中一次转换为Nothing

答案 1 :(得分:0)

我通过使用隐式转换器而不是隐式转换来解决它。

import scala.language.implicitConversions

trait Mapping[I, O]
trait KeyMapping[K, I, O]

trait MappingConverter[M, I, O] {
  def convert(m: M): Mapping[I, O]
}

trait KeyMappingConverter[M, K, I, O] {
  def convert(m: M): KeyMapping[K, I, O]
}

implicit def toMapping[I, O] =
  new MappingConverter[I => O, I, O] {
    def convert(m: I => O): Mapping[I, O] = ???
  }

implicit def toKeyMapping[K, I, O, M](
  implicit mapping: MappingConverter[M, I, O]) =
  new KeyMappingConverter[(K, M), K, I, O] {
    def convert(m: (K, M)): KeyMapping[K, I, O] = ???
  }

def test[K, I, O, M](s: M)(
  implicit converter: KeyMappingConverter[M, K, I, O]): KeyMapping[K, I, O] = ???

val x = test(1 -> { s: String => true })