Created
July 9, 2019 19:08
-
-
Save justinhj/64b94c29c509097fb5b17b3405f6bd97 to your computer and use it in GitHub Desktop.
Flatmap from unit and compose
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 ComposePlay { | |
// Compose takes two Kleisli arrows ( A => F[B], B => F[C] ) and returns A => F[C] | |
// Here I implement unit and compose for Option | |
// Then flatMap is implemented using compose showing that you can make a Monad | |
// with unit and compose... | |
def unitOption[A](a : A) : Option[A] = Some(a) | |
// The core work to be done by compose is must extract the B from the F[B] that the f | |
// produces so that g can be applied | |
def composeOption[A,B,C](f: A => Option[B], g: B => Option[C]): A => Option[C] = { a => | |
val fb = f(a) | |
fb match { | |
case Some(b) => g(b) | |
case None => None | |
} | |
} | |
// The tricky part here is that flatMap takes an F[A] but compose needs an A | |
// so composeOption's first argument passes the fa and returns it | |
// This way the second function gets the F[A] to work with and as you can | |
// see in the composeOption code, the b is extracted from the F[B] and then | |
// we're good to go | |
def flatMapOption[A,B](fa : Option[A])(f: A => Option[B]) = { | |
composeOption((fa : Option[A]) => fa, (a : A) => f(a))(fa) | |
} | |
// A slightly neater version that calls out that the first function is the identity | |
def flatMapOption2[A,B](fa : Option[A])(f: A => Option[B]) = { | |
composeOption[Option[A],A,B](identity, (a : A) => f(a))(fa) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment