2016-06-14 13 views
0

У меня есть Seq[R], и я хочу разделить это в Tuple2[Seq[E], Seq[S]], в то время как я кодирования этого я думал о том, что я мог бы использовать пользовательские Bifunctor для кортежа seqs и как упражнения пытались закодировать это :параметризованном типа псевдоним Bifunctors

import scalaz.Bifunctor 

type MyType[E, S] = (Seq[E], Seq[S]) 

case class MyVali[E, S](tp: (Seq[E], Seq[S]))(implicit bifunctor: Bifunctor[MyType]) { 
    def bimap[C, D](f: (E) => C, g: (S) => D): (Seq[C], Seq[D]) = 
    bifunctor.bimap(tp)(f, g) 

    def leftMap[C](f: (E) => C): (Seq[C], Seq[S]) = 
    bifunctor.leftMap(tp)(f) 

    def rightMap[D](g: (S) => D): (Seq[E], Seq[D]) = 
    bifunctor.rightMap(tp)(g) 

} 

val myValBifunctorInstance = new Bifunctor[MyType] { 
    override def bimap[A, B, C, D](fab: (Seq[A], Seq[B]))(f: (A) => C, g: (B) => D): (Seq[C], Seq[D]) = 
    (fab._1.map(f), fab._2.map(g)) 
} 

MyVali((Seq.empty[String], Seq.empty[Int]))(myValBifunctorInstance).bimap(a => a, b => b) 

Это прекрасно работает, но по какой-то причине неясного мне пришлось объявить параметризованным типа псевдоним, чтобы сделать все это компилировать, а именно type MyType[E, S] = (Seq[E], Seq[S]), и я с трудом понимаю, почему это работает, пока это не будет:

def myValBimap[E, S] = new Bifunctor[Tuple2[Seq[E], Seq[S]]] { 
    override def bimap[A, B, C, D](fab: (A, B))(f: (A) => C, g: (B) => D): (C, D) = ??? 
} 

[ошибка] ... (Seq [Е], Seq [S]) не принимает никаких параметров типа, ожидаемые: два

[ошибка] Защита myValBimap [E, S] = новый бифунктор [Tuple2 [Seq [E], Seq [S]]] {

Является ли компилятор созданием подвески типа 2 (например, вложенной лямбда-типа?), Когда такой псевдоним типа определен?

ответ

1
def myValBimap[E, S] = new Bifunctor[Tuple2[Seq[E], Seq[S]]] { ... } 

Tuple2[...] в приведенном выше Bifunctor не имеет два параметра типа больше, потому что в E и S заполнены.

Например myValBimap[Int, String] пытается создать Bifunctor[(Seq[Int], Seq[String])] и тип (Seq[Int], Seq[String]) явно не имеют два типа параметры.

Вы могли бы написать

  • Bifunctor[({ type λ[α, β] = (Seq[α], Seq[β])})#λ] или
  • Bifunctor[λ[(α, β) => (Seq[α], Seq[β])]] с помощью плагина вид проектора.

Вы должны неявной функции с параметром типа, если вам нужен дополнительный тип, может быть что-то вроде:

implicit def myBimap[F[_]: Functor]: Bifunctor[λ[(α, β) => (F[α], F[β])]] = ??? 

Более простой пример является Functor для дизъюнкции/\/, который использует параметр типа для левая сторона:

implicit def functorDisj[L]: Functor[L \/ ?] = ??? 
implicit def functorDisj[L]: Functor[({ type λ[α] = L \/ α })#λ] = ??? 

О исходной задаче: Это может быть possibl e, чтобы нанести на карту R по номеру E \/ S и использовать separate:

import scalaz._, Scalaz._ 

val integers = List.range(1,10) 
val stringOrInts: List[String \/ Int] = 
    integers.map(i => if (i % 2 == 0) i.right else i.toString.left) 

stringOrInts.separate 
// (List[String], List[Int]) = (List(1, 3, 5, 7, 9),List(2, 4, 6, 8))