Created
March 6, 2018 01:42
-
-
Save sdether/e3ff27491f0e91c1bcb5103f24ea2d86 to your computer and use it in GitHub Desktop.
Desugaring Doobie for comprehension
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
case class Foo(id: Int, name: String) | |
case class Bar(id: Int, name: String) | |
case class FooWithBar(foo: Foo, bars: List[Bar]) | |
// The for-comprehension way | |
def get1(id: Int): ConnectionIO[Option[FooWithBar]] = for { | |
fooOpt <- sql"""SELECT id, name FROM foo WHERE id=$id""".query[Foo].option | |
fooOpt2 <- fooOpt match { | |
case Some(foo) => | |
(for { | |
bars <- sql"""SELECT id,name FROM bar WHERE foo_id=${foo.id}""".query[Bar].to[List] | |
} yield bars).map { bars => | |
Some(FooWithBar(foo, bars)) | |
} | |
case None => None.pure[ConnectionIO] | |
} | |
} yield fooOpt2 | |
// de-sugaring into a flatmap | |
def get2(id: Int): ConnectionIO[Option[FooWithBar]] = sql"""SELECT id, name FROM foo WHERE id=$id""".query[Foo].option.flatMap { | |
case Some(foo) => | |
sql"""SELECT id,name FROM bar WHERE foo_id=$foo.id""".query[Bar].to[List].map(bars => bars).map(bars => | |
Some(FooWithBar(foo, bars))) | |
// Complains about None.type <: Option[FooWithBar], but class Free is invariant in type A. | |
case None => None.pure[ConnectionIO] | |
} | |
// letting IntelliJ de-sugar the for-comprehension | |
def get3(id: Int): ConnectionIO[Option[FooWithBar]] = sql"""SELECT id, name FROM foo WHERE id=$id""".query[Foo].option.flatMap(fooOpt => (fooOpt match { | |
case Some(foo) => | |
sql"""SELECT id,name FROM bar WHERE foo_id=$foo.id""".query[Bar].to[List].map(bars => bars).map(bars => | |
Some(FooWithBar(foo, bars))) | |
case None => None.pure[ConnectionIO] | |
}).map(fooOpt2 => fooOpt2)) | |
// Artificial example using Option[Option[Int] instead of ConnectionIO[Option[FooWithBar]] | |
// f1 & f2 are equivalent | |
def f1(x: Option[Option[Int]]): Option[Option[Int]] = x.flatMap { | |
z => | |
(z match { | |
case Some(y) => Some(Some(y + 1)) | |
case None => Some(None) | |
}).map(a => a) | |
} | |
def f2(x: Option[Option[Int]]): Option[Option[Int]] = x.flatMap { | |
case Some(y) => Some(Some(y + 1)) | |
case None => Some(None) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment