Advertisement
Guest User

Untitled

a guest
Oct 18th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.65 KB | None | 0 0
  1. package ft.typesafety
  2.  
  3. import arrow.core.Option
  4. import arrow.core.getOrElse
  5.  
  6. /**
  7. * Use pattern matching and recursion. No vars, no loops, no overriding.
  8. *
  9. * `Option` is an implementation of optional functionality.
  10. *
  11. * We've made these exercises to give you greater insight into how an optional pattern
  12. * might work in a functional language.
  13. *
  14. * When you see `Option` think: "It may exist, or it may not"
  15. *
  16. * There are two ways to construct an `Option`:
  17. *
  18. * `Some()` represents something that exists
  19. *
  20. * `None` represents something that doesn't exist
  21. *
  22. * We use `Option` in situations where there isn't certainty that a meaningful
  23. * value will be returned to us.
  24. *
  25. *
  26. * TODO - Rewrite these instructions for Kotlin
  27. *
  28. * The `get()` method on the key to value store `Map` is a great example of this.
  29. *
  30. * We expect `get()` to take a key and give us a value in return.
  31. *
  32. * But what happens when our Map doesn't know about the key we gave it?
  33. *
  34. * A Map here is the same as in any other language,
  35. * we just need to tell it about the types we're working with.
  36. *
  37. * This is the type of the key
  38. * |
  39. * | This is the type of the value
  40. * | |
  41. * | |
  42. * val myMap = mapOf<Int, String>( 1 to "one", 2 to "two", ...)
  43. *
  44. *
  45. * When we call `get()` on Map we will always get back an `Option` type
  46. *
  47. * myMap.get(1) = Some("one") //The value exists and it's the string "one"
  48. *
  49. * myMap.get(0) = None //The value doesn't exist so we get None
  50. *
  51. * `Some("one")` and `None` are both of the type Option
  52. *
  53. * Since `Some` and `None` are the same type we can pattern match on them!
  54. *
  55. * We can have one set of logic when we get Some back and a different set
  56. * of logic when we get `None` back!
  57. *
  58. * val mightBeSomething: Option<String> = myMap.get(3)
  59. *
  60. * val result: String = mightBeSomething match {
  61. * case Some(string) => "I got a String back!"
  62. * case None => "I got None back"
  63. * }
  64. *
  65. * Good luck!
  66. *
  67. */
  68.  
  69. object OptionalExercises1 {
  70.  
  71. val config = mapOf("host" to "squareup.com", "port" to "8080")
  72.  
  73. fun getFromConfig(key: String): Option<String> = Option.fromNullable(config[key])
  74.  
  75. fun lengthOfHost(): Option<Int> = getFromConfig("host").map { it.length }
  76.  
  77. fun portPlus1000(): Option<Int> = getFromConfig("port").map { it.toInt() + 1000 }
  78. }
  79.  
  80. object OptionalExercises2 {
  81.  
  82. val hosts = mapOf("host1" to "squareup.com", "host2" to "test.squareup.com", "host3" to "netflix.com")
  83. val envs = mapOf("squareup.com" to "prod", "test.squareup.com" to "test", "amazon.com" to "stage")
  84.  
  85. // Should return the env string if successful or "couldn't resolve" if unsuccessful
  86. fun getEnvForHost(host: String): String = Option.fromNullable(hosts[host])
  87. .flatMap { Option.fromNullable(envs[it]) }
  88. .getOrElse { "couldn't resolve" }
  89.  
  90. // See how many ways you can implement this.
  91. // Will either return "Connected to <squareup host>" or "not connected"
  92. fun connectToSquareupHostsOnly(host: String): String = Option.fromNullable(hosts[host])
  93. .filter { it.endsWith("squareup.com") }
  94. .map { createConnection(it) }
  95. .getOrElse { "not connected" }
  96.  
  97. private fun createConnection(domain: String): String = "connected to $domain"
  98. }
  99.  
  100. /**
  101. * Here we make the trait `Maybe`, which is our version of `Option`
  102. *
  103. * `Just` has the same behavior as `Some`
  104. * `Nothing` has the same behavior as `None`
  105. *
  106. * We use this exercise to illustrate that we can create our own optional behavior
  107. * with just a few functions.
  108. *
  109. */
  110.  
  111. object OptionalExercises3 {
  112.  
  113. interface Maybe<out A>
  114.  
  115. data class Just<A>(val get: A) : Maybe<A>
  116.  
  117. object Nothing : Maybe<kotlin.Nothing>
  118.  
  119. fun <A, B> flatMap(m: Maybe<A>, f: (A) -> Maybe<B>): Maybe<B> = when(m) {
  120. is Just -> f(m.get)
  121. else -> Nothing
  122. }
  123.  
  124. fun <A, B> map(m: Maybe<A>, f: (A) -> B): Maybe<B> = when(m) {
  125. is Just -> Just(f(m.get))
  126. else -> Nothing
  127. }
  128.  
  129. fun <A, B> fold(m: Maybe<A>, default: () -> B, f: (A) -> B): B = when(m) {
  130. is Just -> f(m.get)
  131. else -> default()
  132. }
  133.  
  134. fun <A> orElse(m: Maybe<A>, otherwise: () -> Maybe<A>): Maybe<A> = when(m) {
  135. is Just -> m
  136. else -> otherwise()
  137. }
  138.  
  139. fun <A> orSome(m: Maybe<A>, default: () -> A): A = when(m) {
  140. is Just -> m.get
  141. else -> default()
  142. }
  143.  
  144. fun <A, B, C> map2(m1: Maybe<A>, m2: Maybe<B>, f: (A, B) -> C): Maybe<C> =
  145. flatMap(m1) { a -> map(m2) { b -> f(a, b) } }
  146.  
  147. fun <A> sequence(l: List<Maybe<A>>): Maybe<List<A>> = l.fold(Just(emptyList())) { acc, next ->
  148. map2(acc, next) { xs, x -> xs.plus(x) }
  149. }
  150.  
  151. fun <A, B> ap(m1: Maybe<A>, m2: Maybe<(A) -> B>): Maybe<B> = flatMap(m1) { a ->
  152. map(m2) { f -> f(a) }
  153. }
  154. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement