我试图在模式中使用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" )
但上述内容无法使用以下消息进行编译:
非法依赖方法类型:参数出现在同一部分或前一个参数中的另一个参数的类型
如何处理?
答案 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
函数,如上面的断言所示。