The good parts in scalaz
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

The good parts in scalaz

on

  • 888 views

By Shimi Bandiel from Trainologic for Scalapeno Israel 2013

By Shimi Bandiel from Trainologic for Scalapeno Israel 2013

Statistics

Views

Total Views
888
Views on SlideShare
888
Embed Views
0

Actions

Likes
1
Downloads
31
Comments
0

0 Embeds 0

No embeds

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

The good parts in scalaz Presentation Transcript

  • 1. copyright 2013 Trainologic LTD Scalaz – The Good Parts
  • 2. 2 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Scalaz is one of the famous/infamous libraries in Scala. • In this session we are going to overview some parts of it. • But first of all, who are the intended audience? Scalaz 2
  • 3. 3 copyright 2013 Trainologic LTD Scalaz – The Good Parts • We assume a certain level of familiarity with Scala syntax and core libraries. • You should be comfort with the following declaration: Know Your Scala 3 numbers.foldRight(List.empty[Int]) {_ :: _}
  • 4. 4 copyright 2013 Trainologic LTD Scalaz – The Good Parts • If you are a seasoned Haskell programmer, you’ll find that Scalaz resembles Haskell. • We are going to look at some features of Scalaz without discussing Category Theory. • We will see some of the power of Scalaz without going into the full definitions and laws of the concepts. • All of these have their place, but we don’t have time for it all. • Let’s start with Type Classes… Scalaz 4
  • 5. 5 copyright 2013 Trainologic LTD Scalaz – The Good Parts • First of all let’s make it clear: There is no relationship between Type Classes and OO classes or idioms! • They arrive of course from Haskell  • A Type Class defines a set of operations that must be available on types belonging to this Type Class. • Type Classes are being used extensively in the core libraries in Scala, in 3rd parties and in Scalaz. Type-Classes 5
  • 6. 6 copyright 2013 Trainologic LTD Scalaz – The Good Parts • The first example of a type class in Scalaz we’re going to discuss is Equal. • It provides a type safe equality check. • In contrast to the built-in Scala’s “==“ method. • E.g.: Equal 6 import scalaz._ import Scalaz._ val i1 = 5 //> i1 : Int = 5 val i2 = 6 //> i2 : Int = 6 val s1 = "8" //> s1 : String = 8 i1 == i2 //> res0: Boolean = false i1 == s1 //> res1: Boolean = false i1 === i2 //> res2: Boolean = false // i1 === s1 does not compile
  • 7. 7 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Well, this looks like a simple implicit conversion that provides the “===“ type-safe equality check. • What is the connection to Type Classes here? • Well, the way to create instances of type classes in Scala, is to use implicits. • And you can introduce your own implementations whenever you want… Discussion 7
  • 8. 8 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Consider the following code: Discussion 8 // doesn’t compile here, no implicit Equal new java.lang.Thread() === new java.lang.Thread()// implicit object eqThread extends Equal[java.lang.Thread] { def equal(a1: Thread, a2: Thread) = a1.getId === a2.getId } new java.lang.Thread() === new java.lang.Thread()//> res0: Boolean = false val t1 = new java.lang.Thread() //> t1 : Thread = Thread[Thread-2,5,main] t1 === t1 //> res1: Boolean = true
  • 9. 9 copyright 2013 Trainologic LTD Scalaz – The Good Parts • The Order typeclass provides, well, ordering. • E.g.: Order 9 1 ?|? 2 //> res0: scalaz.Ordering = LT 1 ?|? 2.0 // does not compile
  • 10. 1 0 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Another useful Type Class is Show: Show 10 1.show //> res0: scalaz.Cord = 1 "hello".show //> res1: scalaz.Cord = "hello“ // the following line doesn’t compile here new Thread().show implicit val showThread = Show.shows[Thread] { _.getName } new Thread().show //> res2: scalaz.Cord = Thread-0
  • 11. 1 1 copyright 2013 Trainologic LTD Scalaz – The Good Parts • No more printing “com.bom.mom.X@3249234f” because we forgot to implement toString(). • It will not compile. • You can also provide different printing for different usecases (e.g., verbose mode, admin user, etc…). Discussion 11
  • 12. 1 2 copyright 2013 Trainologic LTD Scalaz – The Good Parts • We all favor using immutable data (and if not you should). • Especially if we’re into functional programming. • However, this means that modification results in creating a new ‘version’ of the object. • This can be quite cumbersome. • Let’s take a look at an example… Lens 12
  • 13. 1 3 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Simple Lens usage: Example 13 case class Customer(name: String, age: Int) case class Stock(name: String, price: Int) case class StockPortfolio(stocks: Map[String, Stock], customer: Customer) val john = Customer("John", 30) //> john : lens.Customer = Customer(John,30) val customerAge = Lens.lensu[Customer, Int]((a, value) ⇒ a.copy(age = value), a ⇒ a.age) val customerName = Lens.lensu[Customer, String]((a, value) ⇒ a.copy(name = value), a ⇒ a.name) val jane = customerName set (john, "Jane")//> jane : lens.Customer = Customer(Jane,30) val johnNextYear = customerAge set (john, 31) //> johnNextYear : lens.Customer = Customer(John,31) val incCustomerAge = customerAge %= {_+1} val johnNextYearAgain = incCustomerAge(john) //> johnNextYearAgain : (lens.Customer, Int) = (Customer(John,31),31)
  • 14. 1 4 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Composition: Example 14 val sampleStock1 = Stock("Sample1", 500) val sampleStock2 = Stock("Sample2", 500) val stockPrice = Lens.lensu[Stock, Int]((a, value) ⇒ a.copy(price = value), a ⇒ a.price) val portfolioCustomer = Lens.lensu[StockPortfolio, Customer]((a, value) ⇒ a.copy(customer = value), a ⇒ a.customer) val portfolioStocks = Lens.lensu[StockPortfolio, Map[String, Stock]]((a, value) ⇒ a.copy(stocks = value), a ⇒ a.stocks) val portfolio = StockPortfolio(customer = john, stocks = Map("Sample1" -> sampleStock1, "Sample2" -> sampleStock2)) portfolioStocks at "Sample1" andThen stockPrice set (portfolio, 9999) //> res0: lens.StockPortfolio = StockPortfolio(Map(Sample1 -> Stock(Sample1,9999), Sample2 -> Stock(Sample2,500)),Customer(John,30))
  • 15. 1 5 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Scenario: we need to perform validation on some data. • We want to accumulate the validations and not throw an exception and break the flow. • Scalaz provides the Validation class which can be used for this purpose. • Let’s see and discuss some examples… Validation 15
  • 16. 1 6 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Validation: Example 16 // Basic Data Types case class Person(name: String, age: Int, yearsInSchool: Int, citizenship : Boolean) // Validation Functions trait PublicInstitue { def checkEducation(p: Person): Validation[String, Person] = { if (p.yearsInSchool < 12) "Not enough education".fail else p.success } def checkCitizenship(p : Person) : Validation[String, Person] = { if (p.citizenship) p.success else "Must be a Citizen".fail } def checkAge(p : Person) : Validation[String, Person] = { if (p.age < 18) "Too young".fail else if (p.age > 65) "Too old".fail else p.success } }
  • 17. 1 7 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Ok, now let’s use the previous validation logic in a stop- on-first-failure strategy: First Usage 17 // let's try to get some persons a job at the Ministry of Wealth: object MinistryOfHealth extends PublicInstitue { def applyForJob(p : Person) : Validation[String, String] = { for { v1 <- checkEducation(p) v2 <- checkCitizenship(p) v3 <- checkAge(p) } yield s"${v1.name}, you got the job" } } // Failure(Must be a Citizen) println( MinistryOfHealth applyForJob Person("John", 30, 15, citizenship = false)) // Success(Shraga, you got the job) println( MinistryOfHealth applyForJob Person("Shraga", 30, 15, citizenship = true)) // Failure(Not enough education) println( MinistryOfHealth applyForJob Person("Dani", 13, 5, citizenship = true))
  • 18. 1 8 copyright 2013 Trainologic LTD Scalaz – The Good Parts • OK, nice. • Now lets accumulate the errors: Accumulation 18 // let's try to get some persons a job at the Ministry of Transportation: object MinistryOfTransportation extends PublicInstitue { def applyForJob(p: Person) = { (checkEducation(p) |@| checkCitizenship(p) |@| checkAge(p)) { case (_, _, p) ⇒ s"${p.name}, you got the job" } } } println(MinistryOfTransportation applyForJob Person("John", 30, 15, citizenship = false)) println(MinistryOfTransportation applyForJob Person("Shraga", 30, 15, citizenship = true)) // Failure(Not enough educationToo young) println(MinistryOfTransportation applyForJob Person("Dani", 13, 5, citizenship = true))
  • 19. 1 9 copyright 2013 Trainologic LTD Scalaz – The Good Parts • First of all, you can use the following line instead of the |@| operator: Discussion 19 (checkEducation(p) ⊛ checkCitizenship(p) ⊛ checkAge(p)) { • Second, concatenating strings is not that useful. • Let’s use a non empty list on the failure side: def applyForJob(p: Person) = { (checkEducation(p).toValidationNel ⊛ checkCitizenship(p).toValidationNel ⊛ checkAge(p).toValidationNel) { … } // Failure(NonEmptyList(Not enough education, Too young)) println(MinistryOfTransportation applyForJob Person("Dani", 13, 5, citizenship = true))
  • 20. 2 0 copyright 2013 Trainologic LTD Scalaz – The Good Parts • We have seen here the use for ApplicativeBuilder operator: |@| • Also known as the “macaulay culkin” operator  ApplicativeBuilder 20
  • 21. 2 1 copyright 2013 Trainologic LTD Scalaz – The Good Parts • And, what if we have a long sequence of validation methods? • We wouldn’t want to type all of them. Right? • We’re not going to discuss it here, but the following code will do just fine: What If? 21 def applyForJob(p: Person) = { val validations = List(checkEducation _, checkCitizenship _, checkAge _) validations.traverse[({type l[a] = ValidationNel[String, a]})#l, Person](_ andThen (_.toValidationNel) apply p) map { case p::_ ⇒ s"${p.name}, you got the job" } }
  • 22. 2 2 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Well, the Validation type is very useful compared to the pre-defined Either type. • Scalaz also provides the / type which is almost like either, but supports for-comprehensions on the right projection. Discussion 22
  • 23. 2 3 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Well, combinators in Validation was nice. • Also, for-comprehensions are nice. • Functors, Applicatives and Monads are very useful. • And they are depicted in Scalaz by appropriate Type Classes. • Let’s do a quick overview… Discussion 23
  • 24. 2 4 copyright 2013 Trainologic LTD Scalaz – The Good Parts • The Functor type class include types that can be mapped on. • Example: Functor Type Class 24 def foo[F[_] : Functor](fs : F[Int]): F[Int] = { fs map {_ + 5} } val numbers = List(1,2,3) //> numbers : List[Int] = List(1, 2, 3) foo(numbers) //> res0: List[Int] = List(6, 7, 8) val optInt = some(5) //> optInt : Option[Int] = Some(5) foo(optInt) //> res1: Option[Int] = Some(10)
  • 25. 2 5 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Applicatives were used in the validation examples. • Let’s understand them more. • E.g.: Applicative 25 val opt1 = some(6) //> opt1 : Option[Int] = Some(6) val opt2 = some(7) //> opt2 : Option[Int] = Some(7) (opt1).<*>(opt2.map(x => (y : Int) => x + y)) //> res0: Option[Int] = Some(13) (opt1 |@| opt2) (_+_) //> res0: Option[Int] = Some(13)
  • 26. 2 6 copyright 2013 Trainologic LTD Scalaz – The Good Parts • We can also lift simple values into the Applicative. • E.g.: Lifting into Applicative 26 (opt1 ⊛ opt2 ⊛ 6.point[Option]) (_+_ +_) //> res1: Option[Int] = Some(19)
  • 27. 2 7 copyright 2013 Trainologic LTD Scalaz – The Good Parts • And there are of course, the famous Monads. • Used in for-comprehensions. • Instances: Option, Traversables, Validation, Reader, Writer, State, IO and many more… Monads 27
  • 28. 2 8 copyright 2013 Trainologic LTD Scalaz – The Good Parts • Another nice type, is the Memo type that provides, well, memoization. • E.g.: Memo 28 def delay = { Thread.sleep(50) 1 } val fac: Int => Int = { case 1 => 1 case n => n*fac(n-1)*delay } val start = java.lang.System.currentTimeMillis println(fac(50)) println(fac(10)) println(fac(50)) val end = java.lang.System.currentTimeMillis println(s"${end-start} millis") // takes around 5000 millis }
  • 29. 2 9 copyright 2013 Trainologic LTD Scalaz – The Good Parts • And now, with memoization: Memo 29 def delay = { Thread.sleep(50) 1 } val fac: Int => Int =Memo.mutableHashMapMemo { case 1 => 1 case n => n*fac(n-1)*delay } val start = java.lang.System.currentTimeMillis println(fac(50)) println(fac(10)) println(fac(50)) val end = java.lang.System.currentTimeMillis println(s"${end-start} millis") // takes around 2500 millis }
  • 30. 3 0 copyright 2013 Trainologic LTD Scalaz – The Good Parts • There are several memoization strategies, including: • weakHashMap • Mutable/immutable maps • Arrays Memo 30