Last active
December 31, 2017 08:15
-
-
Save arjunswaj/8b22965549ac86117873d64513fbf007 to your computer and use it in GitHub Desktop.
Free Monads for File IO
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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