Scala and other Try Log
21 Jan 2019 - friendbear
Try Scala
- RockScalaAdvanced
- AdvancedFunctional Programing
- Monads (is very important 🔴
- Functional Concurrent Programming
- Intro to Parallel Programming on the JVM
- Concurrency Problems on the JVM
- AdvancedFunctional Programing
other
- Contact add-on setup
- https://www.hubspot.com/
- Slack coordination setting
- Contact us https://share.hsforms.com/1JcJyjh3CT5O62BL7h8H0Ww36y3j
/**
* - Monads is very important
*
* trait MonadTemplate[A] {
* def unit(value: A): MonadTemplate[A] // also called pure or apply
* def flatMap[B](f: A => MonadTemplate[B]: MonadTemplate[B] // also called bind
* }
*
* List, Option, Try, Future, Stream, Set are all monads.
*
* Example: List
* Left identity:
* List(x).flatMap(f) = f(x) ++ Nil.flatMap(f) = f(x)
*
* Right identity:
* list.flatMap(x => List(x)) = list
*
* Associativity:
* [a b c].flatMap(f).flatMap(g) =
* (f(a) ++ f(b) ++ f(c)).flatMap(g) =
* f(a).flatMap(g) ++ f(b).flatMap(g) ++ f(c).flatMap(g) =
* [a b c].flatMap(f(_).flatMap(g)) =
* [a b c].flatMap(x => f(x).flatMap(g))
*
* Example: Option
* Left identity:
* Option(x).flatMap(f) = f(x)
* Some(x).flatMap(f) = f(x)
*
* Right identity:
* opt.flatMap(x => Option(x)) = opt
*
* Some(v).flatMap(x => Option(x)) =
* Option(v) =
* Some(v)
* Associativity
* o.flatMap(f).flatMap(g) = o.flatMap(x => f(x).flatMap(g))
*
* Some(v).flatMap(f).flatMap(g) = f(v).flatMap(g)
* Some(v).flatMap(x => f(x).flatMap(g) = f(v).flatMap(g)
*/
Snippet
#!/usr/bin/env amm @main def monads(args: String*) = { // our own Try monad trait Attempt[+A] { def flatMap[B](f: A => Attempt[B]): Attempt[B] } object Attempt { def apply[A](a: => A): Attempt[A] = // call by name try { Success(a) } catch { case e: Throwable => Fail(e) } } case class Success[+A](value: A) extends Attempt[A] { def flatMap[B](f: A => Attempt[B]): Attempt[B] = try { f(value) } catch { case e: Throwable => Fail(e) } } case class Fail(e: Throwable) extends Attempt[Nothing] { def flatMap[B](f: Nothing => Attempt[B]): Attempt[B] = this } /* * left-identity * * unit.flatMap(f) = f(x) * Attempt(x).flatMap(f) = f(x) // Success case! * Success(x).flatMap(f) = f(x) // proved. * * right-identity * * attempt.flatMap(unit) = attempt * Success(x).flatMap(x => Accept(x)) = Accept(x) = Success(x) * * Fail(e).flatMap(...) = Fail(e) * * associativity * * attempt.flatMap(f).flatMap(g) == attempt.flatMap(x => f(x).flatMap(g)) * Fail(e).flatMap(f).flatMap(g) = Fail(e) * Fail(e).flatMap(x => f(x).flatMap(g)) + Fail(e) * * Success(v).flatMap(f).flatMap(g) = * f(v).flatMap(g) OR Fail(e) * * Success(v).flatMap(x => f(x).flatMap(g)) = * f(v).flatMap(g) OR Fail(e) */ val attempt = Attempt { throw new RuntimeException("My own monad, yes!") } println(attempt) /* EXERCISE: 1) implement a Lazy[T] monad = computation which will only be executed when it's needed. unit/apply flatMap */ // 1 - Lazy monad class Lazy[+A](value: => A) { // call by need private lazy val internalValue = value def use: A = internalValue def flatMap[B](f: (=>A) => Lazy[B]): Lazy[B] = f(internalValue) } object Lazy { def apply[A](value: =>A): Lazy[A] = new Lazy(value) } val lazyInstance = Lazy { println("Today I don't feel like doing anything") 42 } println(lazyInstance.use) val flatMappedInstance = lazyInstance.flatMap(x => Lazy { 10 * x }) val flatMappedInstance2 = lazyInstance.flatMap(x => Lazy { 10 * x }) flatMappedInstance.use flatMappedInstance2.use }
#!/usr/bin/env amm @main def ConcurrencyOnJVM(args: String*) = { /** * Exercises * 1) Construct 50 "inception" threads * Thread1 -> Thread2 -> Thread3 -> ... * println("hello from thread #3) * in REVERSE ORDER */ { def inceptionThreads(maxThreads: Int, i: Int = 1): Thread = new Thread(() => { if (i < maxThreads) { val newThread = inceptionThreads(maxThreads, i + 1) newThread.start() newThread.join() } println(s"Hello from thread $i") }) inceptionThreads(50).start() } /* * 2 */ var x = 0 val threads = (1 to 100).map(_ => new Thread(() => x += 1)) threads.foreach(_.start()) /* * 1) what is the biggest value possible for x? 100 * 2) what is the SMALLEST value possible for x? 1 * * thread1: x = 0 * thread2: x = 0 * .... * thread100: x = 0 * * for all threads: x = 1 and write it back to x */ println(x) threads.foreach(_.join()) println(x) }