相互依赖的含义及其与类型族的使用

时间:2014-01-28 08:32:01

标签: scala implicit type-families

我试图在模式中使用type family模仿,其中类型类实例依赖于另一个类型类实例解析的类型,该模式在以下块中显示:

( implicit someTypeResolver: SomeTypeResolver[ a ],
           stringRep: StringRep[ someTypeResolver.SomeType ] )

您可以看到stringRep分辨率取决于someTypeResolver的分辨率。

这是完整的来源

// A typeclass, 
// which is basically just a type-function from type `a` to `SomeType`
trait SomeTypeResolver[ a ] {
  type SomeType
}
object SomeTypeResolver {
  // An instance, which maps type `Int` to `Boolean`
  implicit val int = new SomeTypeResolver[ Int ]{ type SomeType = Boolean }
  // An instance, which maps type `Char` to `String`
  implicit val char = new SomeTypeResolver[ Char ]{ type SomeType = String }
}

// A simple typeclass which maps a type to some string representation
trait StringRep[ a ] {
  val string: String
}
object StringRep {
  implicit val boolean = new StringRep[ Boolean ]{ val string = "I'm a bool" }
  implicit val char = new StringRep[ Char ]{ val string = "I'm a char" }
}

// Having the following function, which is supposed to return a string 
// representation of a type, which `a` is mapped to
def resolve
  [ a ]
  ( implicit someTypeResolver: SomeTypeResolver[ a ],
             stringRep: StringRep[ someTypeResolver.SomeType ] )
  = stringRep.string

// I expect it to behave like so
assert( resolve[ Int ] == "I'm a bool" )
assert( resolve[ Char ] == "I'm a char" )

但上述内容无法使用以下消息进行编译:

  

非法依赖方法类型:参数出现在同一部分或前一个参数中的另一个参数的类型

如何处理?

1 个答案:

答案 0 :(得分:0)

因此,正如错误所述,我们需要以某种方式将stringRep分辨率转移到另一个推迟的部分。为了实现这一点,我们可以实例化一个中间对象,它在apply函数中引入了这个部分:

def resolve
  [ a ]
  ( implicit someTypeResolver: SomeTypeResolver[ a ] )
  = 
  new {
    def apply( implicit stringRep: StringRep[ someTypeResolver.SomeType ] ) =
      stringRep.string
  }

assert( resolve[ Int ].apply == "I'm a bool" )
assert( resolve[ Char ].apply == "I'm a string" )

必须注意的是,使用这种方法,用户必须显式调用apply函数,如上面的断言所示。