Skip to content

Instantly share code, notes, and snippets.

@arjunswaj
Last active December 31, 2017 08:15
Show Gist options
  • Save arjunswaj/8b22965549ac86117873d64513fbf007 to your computer and use it in GitHub Desktop.
Save arjunswaj/8b22965549ac86117873d64513fbf007 to your computer and use it in GitHub Desktop.
Free Monads for File IO
object FreeIO {
// CSV IO
sealed trait CSVIO[A]
case class ReadCSV(reader: Reader) extends CSVIO[Stream[CSVRecord]]
class CSVIOs[F[_]](implicit I: InjectK[CSVIO, F]) {
def readCSV(reader: Reader): Free[F, Stream[CSVRecord]] =
inject(ReadCSV(reader))
}
object CSVIOs {
implicit def apply[F[_]](implicit I: InjectK[CSVIO, F]): CSVIOs[F] = new CSVIOs[F]
}
// CSV Processor
sealed trait CSVProcessor[A]
case class ProcessCSV(csvRecord: CSVRecord) extends CSVProcessor[String]
class CSVProcessors[F[_]](implicit I: InjectK[CSVProcessor, F]) {
import cats.implicits._
type CSVProcessorsF[A] = Free[F, A]
def processCSV(csvRecord: CSVRecord): Free[F, String] =
inject(Stringify(csvRecord))
def processCSVs(csvRecords: Stream[CSVRecord]): Free[F, Stream[String]] =
csvRecords.map(processCSV)
.sequence[CSVProcessorsF, String]
}
// Interpreters
object CSVIOInterpreter extends (CSVIO ~> Future) {
import scala.collection.JavaConverters._
override def apply[A](fa: CSVIO[A]): Future[A] = fa match {
case ReadCSV(reader) => Future.fromTry(Try {
CSVFormat.RFC4180
.withFirstRecordAsHeader()
.parse(reader)
.getRecords // Loads the complete file
.iterator().asScala.toStream
})
}
}
object CSVProcessorInterpreter extends (CSVProcessor ~> Future) {
override def apply[A](fa: CSVProcessor[A]): Future[A] = fa match {
case ProcessCSV(csvRecord) => Future {
// Process the CSV and do a Web service call
}
}
}
// Program
type T1[A] = EitherK[FileIO, CSVIO, A]
type T[A] = EitherK[CSVProcessor, T1, A]
def read(filename: String)(implicit CP: CSVProcessors[T], CI: CSVIOs[T], F: FileIOs[T]): Free[T, Unit] =
for {
reader <- F.getBufferedReader(filename)
records <- CI.readCSV(reader)
_ <- CP.processCSVs(records)
_ <- F.close(reader)
} yield ()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment