私はFree Monads of Catsで遊んでいます。私はCSVレコードを処理するためにDSLを書いています。基本的な操作はCSVレコードを処理することであり、私はprocessCSVRecords
の操作のためにヘルパーsequence
とmap2
の関数を書いています。私はケースクラスの戻り値の型をジェネリック型R
にします。以下は私が使用しているコードです。私は上記のコードをコンパイルしようとすると、なぜFree Monad InterpreterはString to Id [A]を解決しないのですか
import cats.data.Coproduct
import cats.free.Free.inject
import cats.free.{Free, Inject}
import cats.{Id, ~>}
import org.apache.commons.csv.CSVRecord
object ProcessCSVActions {
sealed trait ProcessCSV[A]
case class ProcessCSVRecord[R](csvRecord: CSVRecord) extends ProcessCSV[R]
class ProcessCSVs[F[_]](implicit I: Inject[ProcessCSV, F]) {
private def sequence[S[_], A](fs: Stream[Free[S, A]]): Free[S, Stream[A]] =
fs.reverse.foldLeft[Free[S, Stream[A]]](Free.pure[S, Stream[A]](Stream()))((b, a) => map2(a, b)(_ #:: _))
private def map2[S[_], A, B, C](ra: Free[S, A], rb: Free[S, B])(f: (A, B) => C): Free[S, C] = for {
a <- ra
b <- rb
} yield f(a, b)
def processCSVRecord[R](csvRecord: CSVRecord): Free[F, R] =
inject[ProcessCSV, F](ProcessCSVRecord[R](csvRecord))
def processCSVRecords[R](csvRecords: Stream[CSVRecord]): Free[F, Stream[R]] = {
val res: Stream[Free[F, R]] = for {
csvRecord <- csvRecords
} yield processCSVRecord[R](csvRecord)
sequence[F, R](res)
}
}
object ProcessCSVs {
def apply[F[_]](implicit I: Inject[ProcessCSV, F]): ProcessCSVs[F] = new ProcessCSVs[F]
}
object StringInterpreterOfCSV extends (ProcessCSV ~> Id) {
override def apply[A](fa: ProcessCSV[A]): Id[A] = fa match {
case ProcessCSVRecord(csvRecord) => csvRecord.get(2)
}
}
}
は今、私は私の通訳のために、以下のエラーが表示されます。
[scalac-2.11] found : String
[scalac-2.11] required: cats.Id[A]
[scalac-2.11] (which expands to) A
[scalac-2.11] case ProcessCSVRecord(csvRecord) => csvRecord.get(2)
[scalac-2.11] ^
[scalac-2.11] one error found
Free
とStream
を処理するための適切な方法は何ですか?
編集:
私はハックを発見しました。ケースクラスにはR
というタイプのパラメータを取っています。
case class ProcessCSVRecord[R](csvRecord: CSVRecord, a:Option[R]) extends ProcessCSV[R]
def processCSVRecord[R](csvRecord: CSVRecord): Free[F, R] =
inject[ProcessCSV, F](ProcessCSVRecord[R](csvRecord, None))
インタープリタでは、結果に一致するタイプを明示的に指定しています。
object StringInterpreterOfCSV extends (ProcessCSV ~> Id) {
override def apply[A](fa: ProcessCSV[A]): Id[A] = fa match {
case ProcessCSVRecord(csvRecord, _: Option[String]) => csvRecord.get(2)
}
}
上記の作業はありましたが、私はこのハックの代わりにより良い解決策があることを望みました。
あなたは実際にケースクラスに 'R'を使用していますか?あなたの例では冗長であるように見えるからです。 –
はい。私は自分のプログラムでそれを使っています(理解のために)。私はCSV解析スクリプトを書いており、通常パターンは同じです。だから、私は自分のケースクラスを再利用し、スクリプトのためにプログラムとインタプリタだけを書こうと思っていました。 – arjunswaj