4

私は a と呼ばれるものを持っていますGenerator:

trait Generator[A, B] {
  def generate(in: Seq[A]): Seq[B]
}

Bindこのジェネレーターのインスタンスを提供できます。

object Generator {
  implicit def generatorBind[T]: Bind[({type l[B] = Generator[T, B]})#l] = new Bind[({type l[B] = Generator[T, B]})#l] {

    def map[A, B](generator: Generator[T, A])(f: A => B): Generator[T, B] = new Generator[T, B] {
      def generate(in: Seq[T]): Seq[B] = generator.generate(in).map(f)
    }

    def bind[A, B](generator: Generator[T, A])(f: A =>Generator[T, B]): Generator[T, B] = new Generator[T, B] {
      def generate(in: Seq[T]): Seq[B] = generator.generate(in).flatMap(v => f(v).generate(in))
    }
  }
}

残念ながら、ジェネレーターを適用可能なインスタンスとして使用しようとすると、型の推論は完全に失われます。

val g1 = new Generator[Int, Int] { def generate(seq: Seq[Int]) = seq.map(_ + 1) }
val g2 = new Generator[Int, Int] { def generate(seq: Seq[Int]) = seq.map(_ + 10) }

// doesn't compile
// can make it compile with ugly type annotations
val g3 = ^(g1, g2)(_ / _)

Generator今のところ私の唯一の回避策は、オブジェクトに特殊なメソッドを追加することです。

def ^[T, A, B, C](g1: Generator[T, A], g2: Generator[T, B])(f: (A, B) => C) = 
  generatorBind[T].apply2(g1, g2)(f)

次に、これをコンパイルします。

val g4 = Generator.^(g1, g2)(_ / _)

この問題の回避策はありますか? State[S, A]asを使うと同じような問題が生じるからだと思いますMonad(しかし、Scalaz では に対して特別な扱いがあるようですState)。

4

2 に答える 2

2

明示的に注釈を付けてタイプする場合、またはに変更する場合は、 ApplicativeBuilderを使用できます。g1g2abstract class Generator

// java.lang.Object with Generator[Int, Int] !!!
val badInference = new Generator[Int, Int] { def generate(seq: Seq[Int]) = seq.map(_ + 1) }

val g1: Generator[Int, Int] = new Generator[Int, Int] { def generate(seq: Seq[Int]) = seq.map(_ + 1) }
val g2: Generator[Int, Int] = new Generator[Int, Int] { def generate(seq: Seq[Int]) = seq.map(_ + 10) }
val g3 = (g1 |@| g2)(_ / _)
于 2013-09-20T03:30:57.740 に答える