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

Functional Programming in Kotlin

Mohit S
August 23, 2017

Functional Programming in Kotlin

Mohit S

August 23, 2017
Tweet

More Decks by Mohit S

Other Decks in Programming

Transcript

  1. Tour of Functional Programming • History of Functional Programming •

    What is Functional Programming? • Imperative vs Functional Programming • Pure Functions • Higher Order Functions • Functional Kotlin • Composition • Currying • Partial Application • Functors
  2. Alan Turing • Mathematician and Computer Scientist. • Made numerous

    contributions to foundations of Computer Science. • Developed Turing Machines. (1912-1954)
  3. Alonzo Church • Mathematician. • Made numerous contributions to Logic,

    Mathematics and CS. • Alan Turing’s Phd Advisor. • Developed Lambda Calculus. (1903-1995)
  4. What Lambda Calculus has given us? • Lambdas • Pure

    functions • Higher order functions • Recursion • Lazy evaluation • Pattern matching ...
  5. Programming Languages Lisp, Haskell, ML, Erlang, … C, Simula 6,

    C++, SmallTalk, Java, etc.. Research/Academic Main stream
  6. What is Functional Programming? A style of programming where you

    focus on transforming data with functions that don’t have side effects.
  7. Imperative vs. Functional Programming Problem: Find the total price of

    all the Computer Science books in list below. • Effective Java – Joshua Bloch, $45.2, Category: CS • Design Patterns – Gangs of Four, $37.48, Category: CS • Topology – James Munkres, $94.10, Category: Math • Gravitation – Kip Thorne, $48.00, Category: Physics • Algebraic Topology – Hatcher, $39.82, Category: Math …
  8. Imperative Approach data class Book(val title: String, val price: Double,

    val category: Category) enum class Category { MATHEMATICS, COMPUTER_SCIENCE, PHYSICS }
  9. Imperative Approach val bookList = listOf(book1, book2, book3, book4, book5)

    var sum = 0.0 for (book in bookList) { if (book.category == Category.COMPUTER_SCIENCE) { sum += book.price } } println(sum) // 82.60
  10. Functional Approach val bookList = listOf(book1, book2, book3, book4, book5)

    val ans = bookList .filter { it.category == Category.COMPUTER_SCIENCE } .sumByDouble { it.price } println(sum) // 82.60
  11. List Functions • Filter • Map • Flatmap • Fold

    • FoldRight • Flatten • GroupBy • Reduce …
  12. Impure Function class Account(private var balance: Int) { fun credit(amount:

    Int): Int { balance += amount return balance } }
  13. Impure Function val account = Account(100) val newAmount1 = account.credit(100)

    // 200 // Uh-Oh! Not a Pure Function L val newAmount2 = account.credit(100) // 300
  14. Impure Function var a: Int = 0 fun increment() {

    a += 1 // mutating global state }
  15. Pure Function square :: Int -> Int val square =

    {x: Int -> x * x} 1. No side effects. 2. Returns same result given same argument(s) 3. Does not depend on external mutable state
  16. What is a Higher Order Function? •A function that takes

    another function as a parameter or returns a function as a parameter.
  17. Function Composition val square = {x : Int -> x

    * x } val add2 = { x : Int -> x + 2 } + 2 +
  18. Function Composition fun compose(f: (Int) -> Int, g: (Int) ->

    Int ): (Int) -> (Int) { return { x : Int -> f(g(x)) } }
  19. Function Composition val square = {x : Int -> x

    * x } val add2 = { x : Int -> x + 2 } val squareAddTwo = compose(square, add2) squareAddTwo(2) // returns 16
  20. Function Composition val square = {x : Int -> x

    * x } val add2 = { x : Int -> x + 2 } val squareAddTwo = square.compose(add2) squareAddTwo(2) // returns 16
  21. Function Composition Extension fun ( (Int) -> Int ).compose( g:

    (Int) -> (Int) ) : (Int) -> Int { return {x : Int -> this(g(x))} } f : Int -> Int g : Int -> Int f(g(x)) : Int -> Int
  22. Function Composition Extension val square = {x : Double ->

    x * x } val add2 = { x : Double -> x + 2 } val squareAddTwo = square.compose(add2)
  23. General Function Comp Extension infix fun <P1, P2, R> (

    (P2) -> R ).compose( g: (P1) -> (P2) ): (P1) -> R { return {x -> this(g(x))} } f : P2 -> R g : P1 -> P2 f(g(x)) : P1 -> R
  24. Function Composition Extension val square = {x : Double ->

    x * x } val add2 = { x : Double -> x + 2 } val squareAddTwo = square compose add2
  25. Haskell Function Composition square x = x * x add2

    x = x + 2 ans = (square . add2) 2 -- 16 Built in Operator for composition.
  26. Form Validation w/ Function Composition val password = editText.text val

    validator = isGreaterThan8Chars compose hasUpperCaseChar compose hasNumber validator(password)
  27. Partial Application val add = { x: Int, y: Int

    -> x + y } val add2 = {y: Int -> 2 + y } Fix a value for x.
  28. Partial Application Extension infix fun <P1, P2, R> ((P1, P2)

    -> R).partially (x: P1) : (P2) -> R { return { p2: P2 -> this(x, p2)} } Fixed value for P1 f : (P1, P2) -> R g : (P2) -> R
  29. Partial Application val add = { x: Int, y: Int

    -> x + y } val add2 = add partially 2 add2(3) // returns 5
  30. Partial Application f : (Int -> Int-> Int)-> Int (arity:

    3) Decompose f to function with lower arity: g : (Int -> Int) -> Int (arity: 2)
  31. Haskell Partial Application addNums :: Num a => a ->

    a -> a -> a addNums a b c = a + b + c addNums 1 2 3 -- 6 addNumsTo2 :: Num a => a -> a -> a addNumsTo2 = addNums 2 addNumsTo2 3 4 -- 9 How do I do this in Kotlin?
  32. Overload invoke // Marker class for non applied param class

    Partial<P2> fun <T> partial(): Partial<T> = Partial() operator fun <P1, P2, R> ( (P1, P2) -> R ).invoke( x: P1, y: Partial<P> = Partial(y) ): (P2) -> R { return { p2: P2 -> this(x, p2)} }
  33. Partial Application without extension val add = { x: Int,

    y: Int -> x + y } val add2 = add(2) add2(3) // 2 + 3 = 5
  34. Currying f : (Int -> Int-> Int)-> Int Decompose f

    into single argument functions: g : (Int) -> (Int -> Int) h : (Int) -> Int
  35. Currying val sumNums = { a: Int, b: Int, c:

    Int -> a + b + c } val ans = sumNums.curried()(1) .curried()(2) .curried()(3) println(ans) // 6
  36. Currying f : (P1 -> P2 -> P3) -> R

    g : (P1) -> (P2 -> P3) -> R) fun <P1, P2, P3, R> ((P1, P2, P3) -> R).curried(): (P1) -> ((P2, P3) -> R) { return { p1: P1 -> { p2: P2, p3: P3 -> this(p1, p2, p3) } } }
  37. Haskell Function Currying sumNums :: Num a => a ->

    a -> a -> a -> a sumNums a b c d = a + b + c + d -- all functions in Haskell take just one argument. ans = sumNums 1 2 3 4 -- 10
  38. Partial Application vs. Currying • Similarity: • Both decrease number

    of arguments (arity). • Difference: • Partial application decreases number of arguments by 1. • Currying decomposes multi argument functions into multiple 1 argument functions.
  39. Common Theme: Reusability OOP Functional Programming • Interface Segregation Principle

    • Abstract Factory • Decorator Functions • Factory Method • Facade • …
  40. List Functor Example val spaces = listOf(”Topological space", "Metric Space",

    "Vector Space", "Manifold") val nameLengths = spaces.map { it.length } println(nameLengths) // [17, 12, 12, 8]
  41. What is a Functor? • Functor is a type that

    can be mapped over. The type has a mapping function defined on it. The mapping is homomorphic. class Functor map : ( (a -> b) -> f a ) -> f b Function from a to b Functor on a Functor on b
  42. Option Example sealed class Option<out A> { object None :

    Option<Nothing>() data class Some<out A>(val value: A) : Option<A>() } a Some(a) Nothing
  43. Option Mapping Example sealed class Option<out A> { object None

    : Option<Nothing>() data class Some<out A>(val value: A) : Option<A>() inline fun <B> map(f: (A) -> B): Option<B> = when (this) { is Option.None -> this is Option.Some -> Option.Some(f(value)) } }