Either, Some or None: An introduction to monadic structures and functional programming

456d07b3f7a1ab66502e232fd9b1d378?s=47 Edson Hilios
September 29, 2017

Either, Some or None: An introduction to monadic structures and functional programming

We will discuss and understand the monadic structures, going through the most important monads, it's operations and main advantages of the functional programming using Scala, Kotlin, Swift, a little bit of Clojure and why not JavaScript.

During the talk we should also realize why concepts as laziness and immutable data are the cornerstone of high throughput threaded systems and how its guarantee reliability and performance.

By the end of the day you should know by heart the main monads and how to use them solve different day-by-day problems and deeply in love with functional programming.


Edson Hilios

September 29, 2017


  1. Either, Some or None An introduction to monadic structures and

    functional programming September 29th, São Paulo, Brazil #monads #functional_programming #category_theory_applied
  2. Edson Hilios MSc. Transp. Engineering & BSc. Engineering Software Engineer

    at _____
  3. What I would like to know about monadic structures and

  4. Why talk about monads? • Implemented in major modern languages:

    • Provides simple ways of express complex computation; • They are hard to read about because of specific vocabulary;
  5. Goals • A soft theory of Monad • Monodic structures

    and operations • Some common monads • Real use cases • Recap
  6. WTF is a Monad?

  7. If this than that Monads express decisions about how and

    which conditions a software should execute. It allows you to handle and route different inputs/outputs without repeating yourself.
  8. It's a design pattern to describe and manipulate flows of

  9. Useful monad properties • Composable • Polymorphic • Immutable •

    Lazily evaluated
  10. Interacting with the Monads • Map • Filter • Aggregate

    • Group
  11. The 3 Monadic laws trait Monoid[A] { // The identity

    def get[A]: A // The functor def map[B](f: A => B): Monad[B] // The bind def flatMap[B](f: A => Monad[B]): Monad[B] } Scala
  12. Show me the Monads

  13. The optional pattern val aString: String = "Hello, world!" val

    len: Int = aString.length Scala
  14. The optional pattern val aString: String = null val len:

    Int = aString.length //=> java.lang.NullPointerException Scala
  15. The optional pattern val maybeString: Option[String] = Some("Hello, world!") val

    maybeLen: Int = maybeString.map(_.length).getOrElse(-1) Scala
  16. The optional pattern val maybeString: String? = "Hello, world!" val

    maybeLen = maybeString?.length ?: -1 Kotlin
  17. The optional pattern let maybeString: String? = "Hello, world!" let

    maybeLen = maybeString.length ?? -1 Swift
  18. The continuation monad (some-> (maybe-a-result from-db) (then-do-something) (then-another) (and-finishes)) Clojure

    Execute if last result is not nil It will return the value or nil Pass the result to the next fn
  19. Call me Maybe s::String -> Maybe String s "" =

    Nothing s x = Just x Haskell
  20. The identity monad val query: Option[String] = Option(myNullableOutput) query match

    { case Some(q) => myTable.filter(_.name == q) case None => myTable.all() } Scala
  21. Exception handling val maybeAnOperation: Try[Any] = Try { potentiallyHarmfulOperation() }

    match { case Success(s: Any) => ??? case Failure(e: ArithmeticException) => ??? case Failure(e: Exception) => ??? } Scala
  22. The functor def firstFunctor(x: Any): Try[String] = ??? def secondFunctor(y:

    String): Try[Int] = ??? def thirdFunctor(z: Int): Try[MyType] = ??? maybeAnException .map(firstFunctor) .map(secondFunctor) .map(thirdFunctor) Try[Any] Try[Try[String]] Try[Try[Try[Int]]] Try[Try[Try[Try[MyType]]]] Scala
  23. Bind operations def firstFunctor(x: Any): Try[String] = ??? def secondFunctor(y:

    String): Try[Int] = ??? def thirdFunctor(z: Int): Try[MyType] = ??? maybeAnException .flatMap(firstFunctor) .flatMap(secondFunctor) .flatMap(thirdFunctor) Try[Any] Try[String] Try[Int] Try[MyType] Scala
  24. Either this or that val json: Either[JsError, JsSuccess] = parse("""{"foo":

    "bar"}""") json match { case JsSuccess(o) => println("OK") case JsError(err) => println(err.list) } Scala
  25. Applicative functor def nonEmpty(s: Option[String]): Validated[Invalid, Valid] val isValid =

    ( nonEmpty("Some string") |@| nonEmpty("") |@| nonEmpty("Other str") |@| nonEmpty(null) ).fold(left => false, rigth => true) Cats
  26. Valid Invalid("Cannot be blank") Valid Invalid("Cannot be null") Holomorphism {

    "1": "Some string", "2": "", "3": "Other str", "4": null } JSON
  27. Right or left identity def httpRequest(input: Either[Valid, Invalid]): HttpResponse =

    input.fold( left => HttpResponse(StatusCodes.BadRequest), right => HttpResponse(StatusCodes.OK)) Scala
  28. Future pattern (def eventualString (future (Thread/sleep 1000) "Hello, async!") @eventualString

    ;; => Returns Hello, async after 1s Clojure
  29. Asynchronous operations val eventualLength: Task[String] = Task { Thread.sleep(1000) "Hello,

    async!" } map { result => result.length } eventualLength.run() // => Eventually returns 13 after 1s Scalaz
  30. Sequential or concurrent firstTask .flatMap(secondTask) .flatMap(thirdTask) .run() // => Task[T]

    Task.gatherUnordered( firstTask, secondTask, thirdTask ).run() // => Task[List(f, s, t)] Scalaz Scalaz
  31. Assigning callbacks firstTask.flatMap(secondTask).flatMap(thirdTask) .runAsync { case Success(s) => // Perform

    side effects case Failure(e) => // Do something on failure } Scalaz
  32. It's all about Promises let eventualResponse = new Promise(function() {

    setTimeout(() => resolve("Hello, world!"), 2000) }) eventualResponse .then(applyFunctor) .then(msg => console.log("Apply side-effects!")) ES2016
  33. The observable pattern val observer = new Observer[Any] { def

    onNext(elem: Any): Future[Ack] = Continue def onError(ex: Throwable): Unit = ex.printStackTrace() def onComplete(): Unit = println("Completed") } Monix
  34. Observable operations • Group by batches or time intervals; •

    Fork and merge streams; • Handle errors and apply retry strategies; • Delay execution and back-pressure.
  35. Becoming reactive Rx.Observable.webSocket('ws://localhost:8000') .retryWhen((errors) => { return Rx.Observable.timer(5000) // retry

    in 5 secs }) .groupBy((msg) => msg.category) .throttle(1000) // One message per sec and discard the rest .subscribe((msgs) => console.log(msgs)) ES2016
  36. Recapping the monads • Maybe is useful to handle failures

    scenarios; • Either for validations and data deserialization; • Future lets you create asynchronous operations;
  37. Monads FTW • SwiftZ and Runes for Swift • Kathegory

    for Kotlin • Scalaz, Cats and Monix for Scala • ReactiveX (aka Rx): Scala, C#, C++, Kotlin, Swift and many others
  38. Homework • Reader and Writer Monads • Monad Transformers •

    Free Monad and Free Applicative • Lenses, Kleisli, and others;
  39. Twitter: @hilios Site: http://edson.hilios.com.br Talk: https://speakerdeck.com/hilios GitHub: https://github.com/hilios Thank you!