Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

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
Tweet

More Decks by Edson Hilios

Other Decks in Technology

Transcript

  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

    View full-size slide

  2. Edson Hilios
    MSc. Transp. Engineering & BSc. Engineering
    Software Engineer at _____

    View full-size slide

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

    View full-size slide

  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;

    View full-size slide

  5. Goals
    ● A soft theory of Monad
    ● Monodic structures and operations
    ● Some common monads
    ● Real use cases
    ● Recap

    View full-size slide

  6. WTF is a Monad?

    View full-size slide

  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.

    View full-size slide

  8. It's a design pattern to describe and
    manipulate flows of data

    View full-size slide

  9. Useful monad properties
    ● Composable
    ● Polymorphic
    ● Immutable
    ● Lazily evaluated

    View full-size slide

  10. Interacting with the Monads
    ● Map
    ● Filter
    ● Aggregate
    ● Group

    View full-size slide

  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

    View full-size slide

  12. Show me the Monads

    View full-size slide

  13. The optional pattern
    val aString: String = "Hello, world!"
    val len: Int = aString.length
    Scala

    View full-size slide

  14. The optional pattern
    val aString: String = null
    val len: Int = aString.length
    //=> java.lang.NullPointerException
    Scala

    View full-size slide

  15. The optional pattern
    val maybeString: Option[String] = Some("Hello, world!")
    val maybeLen: Int = maybeString.map(_.length).getOrElse(-1)
    Scala

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  19. Call me Maybe
    s::String -> Maybe String
    s "" = Nothing
    s x = Just x
    Haskell

    View full-size slide

  20. The identity monad
    val query: Option[String] = Option(myNullableOutput)
    query match {
    case Some(q) => myTable.filter(_.name == q)
    case None => myTable.all()
    }
    Scala

    View full-size slide

  21. Exception handling
    val maybeAnOperation: Try[Any] = Try {
    potentiallyHarmfulOperation()
    } match {
    case Success(s: Any) => ???
    case Failure(e: ArithmeticException) => ???
    case Failure(e: Exception) => ???
    }
    Scala

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  26. Valid
    Invalid("Cannot be blank")
    Valid
    Invalid("Cannot be null")
    Holomorphism
    {
    "1": "Some string",
    "2": "",
    "3": "Other str",
    "4": null
    }
    JSON

    View full-size slide

  27. Right or left identity
    def httpRequest(input: Either[Valid, Invalid]): HttpResponse =
    input.fold(
    left => HttpResponse(StatusCodes.BadRequest),
    right => HttpResponse(StatusCodes.OK))
    Scala

    View full-size slide

  28. Future pattern
    (def eventualString
    (future (Thread/sleep 1000)
    "Hello, async!")
    @eventualString
    ;; => Returns Hello, async after 1s
    Clojure

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  31. Assigning callbacks
    firstTask.flatMap(secondTask).flatMap(thirdTask)
    .runAsync {
    case Success(s) => // Perform side effects
    case Failure(e) => // Do something on failure
    }
    Scalaz

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  34. Observable operations
    ● Group by batches or time intervals;
    ● Fork and merge streams;
    ● Handle errors and apply retry strategies;
    ● Delay execution and back-pressure.

    View full-size slide

  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

    View full-size slide

  36. Recapping the monads
    ● Maybe is useful to handle failures scenarios;
    ● Either for validations and data deserialization;
    ● Future lets you create asynchronous operations;

    View full-size slide

  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

    View full-size slide

  38. Homework
    ● Reader and Writer Monads
    ● Monad Transformers
    ● Free Monad and Free Applicative
    ● Lenses, Kleisli, and others;

    View full-size slide

  39. Twitter: @hilios
    Site: http://edson.hilios.com.br
    Talk: https://speakerdeck.com/hilios
    GitHub: https://github.com/hilios
    Thank you!

    View full-size slide