Last active
August 13, 2017 15:02
-
-
Save yannick-cw/2ad9ede65acf6b56343d1e4430a3b4ff to your computer and use it in GitHub Desktop.
Examples with two phantom types patterns
This file contains hidden or 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 DbRepo { | |
sealed trait State | |
sealed trait Fresh extends State | |
sealed trait IndexCreated extends State | |
sealed trait IndexReady extends State | |
sealed trait ReadyToRead extends State | |
def apply(): DbRepo[Fresh] = new DbRepo | |
} | |
class DbRepo[RepoState <: DbRepo.State] private { | |
import DbRepo._ | |
def readDoc(id: String)(implicit ev: RepoState =:= IndexReady): Future[(String, DbRepo[IndexReady])] = { | |
println("fetching document ...") | |
Future.successful(("theDoc", new DbRepo)) | |
} | |
def writeDocument(doc: String)(implicit ev: RepoState =:= IndexReady): Future[DbRepo[IndexReady]] = { | |
println("indexing ...") | |
Future.successful(new DbRepo) | |
} | |
def addMappingSettings(mapping: String)(implicit ev: RepoState =:= IndexCreated): Future[DbRepo[IndexReady]] = { | |
println("adding mapping") | |
Future.successful(new DbRepo) | |
} | |
def createIndex(name: String)(implicit ev: RepoState =:= Fresh): Future[DbRepo[IndexCreated]] = { | |
println("creating index") | |
Future.successful(new DbRepo) | |
} | |
} | |
object Indexing extends App { | |
val doc1 = for { | |
created <- DbRepo().createIndex("testIndex") | |
ready <- created.addMappingSettings("test mapping") | |
written <- ready.writeDocument("Hi") | |
(doc, index) <- written.readDoc("id1") | |
} yield doc | |
doc1.foreach(println) | |
// creating index | |
// adding mapping | |
// indexing ... | |
// fetching document ... | |
// "theDoc" | |
DbRepo().writeDocument("not gonna work") | |
// Cannot prove that DbRepo.Fresh =:= DbRepo.IndexReady | |
} | |
object LoanPhantoms { | |
case class LoanApplication[Status] private[Loans] ( | |
name: String, | |
actualRepaymentYears: Option[Int] = None, | |
info: Option[String] = None | |
) | |
trait Applied | |
trait Approved | |
trait Enriched | |
type LoanApplied = LoanApplication[Applied] | |
type LoanApproved = LoanApplication[Approved] | |
type LoanEnriched = LoanApplication[Enriched] | |
def applyLoan(name: String): LoanApplication[Applied] = LoanApplication[Applied](name) | |
def approve: Kleisli[Option, LoanApplied, LoanApproved] = | |
Kleisli(l => Some(l.copy(actualRepaymentYears = Some(12)))) | |
def enrich: Kleisli[Option, LoanApproved, LoanEnriched] = | |
Kleisli(l => Some(l.copy(info = Some("enriched it")))) | |
val l: LoanApplication[Applied] = applyLoan("me") | |
val op: Kleisli[Option, LoanApplied, LoanEnriched] = approve andThen enrich | |
val loan: Option[LoanEnriched] = op run l | |
// val nop = enrich andThen approve | |
// doesn't compile | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment