Skip to content

Instantly share code, notes, and snippets.

@joel113
Forked from linasm/forcomp.scala
Created October 8, 2021 20:59
Show Gist options
  • Select an option

  • Save joel113/9149c8be0cec486044017c551435d161 to your computer and use it in GitHub Desktop.

Select an option

Save joel113/9149c8be0cec486044017c551435d161 to your computer and use it in GitHub Desktop.
Comprehending the For-Comphension talk, Vilnius, Nov 2018
sealed abstract class Perhaps[+A] {
def foreach(f: A => Unit): Unit
def map[B](f: A => B): Perhaps[B]
def flatMap[B](f: A => Perhaps[B]): Perhaps[B]
def withFilter(f: A => Boolean): Perhaps[A]
}
case class YesItIs[A](value: A) extends Perhaps[A] {
override def foreach(f: A => Unit): Unit = f(value)
override def map[B](f: A => B): Perhaps[B] = YesItIs(f(value))
override def flatMap[B](f: A => Perhaps[B]): Perhaps[B] = f(value)
override def withFilter(f: A => Boolean): Perhaps[A] = if (f(value)) this else Nope
}
case object Nope extends Perhaps[Nothing] {
override def foreach(f: Nothing => Unit): Unit = ()
override def map[B](f: Nothing => B): Perhaps[B] = this
override def flatMap[B](f: Nothing => Perhaps[B]): Perhaps[B] = this
override def withFilter(f: Nothing => Boolean): Perhaps[Nothing] = this
}
val y3 = YesItIs(3)
val y4 = YesItIs(4)
val n = Nope
// foreach:
for {
a <- y3
} println(a)
y3.foreach(a => println(a))
// map:
for {
a <- y3
} yield a * a
y3.map(a => a * a)
// flatMap/map:
for {
a <- y3
b <- y4
} yield a * b
y3.flatMap(a => y4.map(b => a * b))
// combining Perhaps with Try:
import scala.util.Try
for {
a <- y4
} yield for {
b <- Try(100 / a)
} yield s"100/$a=$b" // YesItIs(Success(100/4=25))
y4.map { a =>
Try(100 / a).map { b =>
s"100/$a=$b"
}
}
// withFilter:
for {
a <- y3
if a > 1
b <- y4
} yield a * b
y3.withFilter(a => a > 1).flatMap(a => y4.map(b => a * b))
// assignment:
for {
a <- y3
b <- y4
c = a * b
} yield c
y3.flatMap { a =>
y4.map { b =>
val c = a * b
c
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment