Last active
June 22, 2018 23:13
-
-
Save anthonynsimon/c9384d2ca04c9b2cf8390d3511de68a6 to your computer and use it in GitHub Desktop.
FP playground
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
trait Functor[F[_], A] { | |
def fmap[B](f: (A) => B): F[B] | |
} | |
trait Applicative[F[_], A, B] { | |
def liftA(f: F[A]): F[B] | |
} | |
def fmap[A, B](f: (A) => B): (Option[A]) => Option[B] = { | |
case Some(x) => Option(f(x)) | |
case None => None | |
} | |
def liftA[A, B](f: Option[(A) => B]): Option[A] => Option[B] = { | |
case Some(x) => f.fmap(ff => ff(x)) | |
case None => None | |
} | |
def compose[A, B, C](f: (A) => B, g: (B) => C): (A) => C = x => g(f(x)) | |
implicit class optionFunctor[A](x: Option[A]) extends Functor[Option, A] { | |
override def fmap[B](f: A => B): Option[B] = x match { | |
case Some(v) => Option(f(v)) | |
case None => None | |
} | |
} | |
implicit class optionApplicative[A, B](x: Option[(A) => B]) extends Applicative[Option, A, B] { | |
override def liftA(v: Option[A]): Option[B] = x match { | |
case Some(f) => fmap(f)(v) | |
case None => None | |
} | |
} | |
def square: (Int) => Int = x => x * x | |
def cube: (Int) => Int = square compose square | |
Option(2) fmap square | |
(None: Option[Int]) fmap square | |
liftA (Option(square)) (Option(2)) | |
Option(square) liftA Option(2) |
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
trait Functor [C[_], A] { | |
def fmap[B](f: (A) => B): C[B] | |
} | |
sealed trait Maybe[+A] | |
object Maybe { | |
def apply[A](v: A): Maybe[A] = Just(v) | |
} | |
case object Nothing extends Maybe[Nothing] | |
case class Just[A](v: A) extends Maybe[A] | |
implicit class MaybeFunctor[A](m: Maybe[A]) extends Functor[Maybe, A] { | |
def fmap[B](f: A => B): Maybe[B] = m match { | |
case Nothing => Nothing | |
case Just(v) => Maybe(f(v)) | |
} | |
} | |
Just(10) fmap (x => x + 2) | |
Just("").fmap(_ + "101") | |
//Just(10) liftA Maybe((x: Int) => x * x) | |
//Maybe((x: Int) => x * x) liftA Just(10) |
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
import scala.concurrent.{ExecutionContext, Future} | |
object Monads extends App { | |
trait Monad[F[_]] { | |
def flatMap[A, B](a: F[A], f: A => F[B]): F[B] | |
def pure[A](a: A): F[A] | |
} | |
case class User(id: Int) | |
def findUser[F[_]](id: Int)(implicit m: Monad[F]): F[User] = { | |
m.flatMap(m.pure(id), (x: Int) => m.pure(User(x))) | |
} | |
def deleteUser[F[_]](user: User)(implicit m: Monad[F]): F[User] = { | |
m.flatMap(m.pure(user), (user: User) => m.pure(user.copy(-1))) | |
} | |
implicit def futureMonad(implicit executionContext: ExecutionContext): Monad[Future] = new Monad[Future] { | |
override def pure[A](a: A): Future[A] = Future.successful(a) | |
override def flatMap[A, B](a: Future[A], f: A => Future[B]): Future[B] = a.flatMap(f) | |
} | |
case class Id[A](a: A) | |
implicit def idMonad: Monad[Id] = new Monad[Id] { | |
override def pure[A](a: A): Id[A] = Id(a) | |
override def flatMap[A, B](a: Id[A], f: A => Id[B]): Id[B] = f(a.a) | |
} | |
import scala.concurrent.ExecutionContext.Implicits.global | |
def program[F[_]](implicit m: Monad[F]): F[User] = { | |
m.flatMap(findUser[F](5), (x: User) => deleteUser[F](x)) | |
} | |
val x = program[Future] | |
} |
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
class Monad[A](value: A) { | |
def get: A = value | |
def map[B](f: A => B): Monad[B] = { | |
Monad(f(value)) | |
} | |
def flatMap[B](f: A => Monad[B]): Monad[B] = { | |
f(value) | |
} | |
} | |
object Monad { | |
def apply[A](value: A): Monad[A] = new Monad(value) | |
} | |
Monad(15) | |
.map(_ + 10) | |
.flatMap(x => Monad(x + 20)) | |
.get | |
val z = for { | |
x <- Monad(15) | |
y <- Monad(x + 10) | |
} yield y | |
z.get | |
Monad(15) | |
.map(_ + 10) | |
.flatMap(x => Monad(s"hello $x")) | |
.get |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment