从功能转换为自定义类型集

时间:2015-06-11 23:21:30

标签: scala implicit-conversion typeclass

我有一组看起来像这样的类,它们(令人讨厌)不在单个继承层次结构中:

trait Mxy[A,B] { def apply(a: A): B }
trait Mzz[ C ] { def apply(c: C): C }
trait Mix[  B] { def apply(i: Int): B }
trait Mxi[A  ] { def apply(a: A): Int }
trait Mii      { def apply(i: Int): Int }

面临的挑战是使用转换器将Function1映射到这些类中(因此您可以调用.m来切换);直接隐式转换使得很难弄清楚代码实际上在做什么。

只要最具体的M总是好的,那就可行了。您可以编写类似于

的隐式转换
abstract class MxyMaker[A, B] { def m: Mxy[A, B] }
abstract class MiiMaker       { def m: Mii       }

trait Priority2 {
  implicit def f2mxy[A, B](f: Function1[A, B]) = 
    new MxyMaker[A, B] { def m = new Mxy[A, B] { def apply(a: A) = f(a) } }
}
// Bunch of missing priorities here in the full case
object Convert extends Priority2 {
  implicit def f2mii[A](f: Function1[A, Int])(implicit evA: Int =:= A) = 
    new MiiMaker { def m = new Mii{ 
        def apply(i: Int) = (f.asInstanceOf[Function1[Int,Int]]).apply(i) 
    } }
}

现在每当你有一个Int => Int时,你就得到一个Mii,而对于其他任何东西,你得到一个Mxy。 (如果您没有要求evA,则((a: Any) => 5).m会出现Mii,因为其输入参数参数中的Function1会出现逆差。)

到目前为止一切顺利。但是,如果您所处的环境不需要Mii而是Mxy

def muse[A, B](m: Mxy[A,B]) = ???

现在推断出最具体的类型不是你想要的。但是,唉,

scala> muse( ((i: Int) => 5).m )
  <console>:18: error: type mismatch;
   found   : Mii
   required: Mxy[?,?]
                muse( ((i: Int) => 5).m )
                                      ^

现在怎样?如果MxyMii的超类,那就没问题了,但事实并非如此,我无法改变它。我可以使用输出类型对m进行参数化,并根据输出类型进行一组类似类类型的事情,然后让用户手动输入.m[Mxy] 。但是我想跳过手动部分并以某种方式从调用muse中获取类型上下文而不会弄乱像val mippy = ((i: Int) = 5).m这样的内容。

精明的人可能会在野外想到这样的情况,但是更容易使用这种“最小化”来使原则正确。

0 个答案:

没有答案