F, g: G)(implicit ea: EApply[T, F, G]): ea.Out = ea(t, f, g) } trait EApply[T, F, G] { type Out def apply(t: T, f: F, g: G): Out } object EApply { def apply[T, F, G](implicit ea: EApply[T, F, G]) = ea implicit def applyF[T, R, G]: EApply[T, T => R, G] = new EApply[T, T => R, G] { type Out = R def apply(t: T, f: T => R, g: G) = f(t) } implicit def applyG[T, R, F]: EApply[T, F, T => R] = new EApply[T, F, T => R] { type Out = R def apply(t: T, f: F, g: T => R) = g(t) } } ApplyEither(1, { (x: Int) => 42 }, { (x: Double) => "no" }) // 42: EApply[Int, Function1[Int, Int], Function1[Double, String]].Out ApplyEither(2.0, { (x: Int) => 42 }, { (x: Double) => "no" }) // "no": EApply[Int, Function1[Int, Int], Function1[Double, String]].Out