$30 off During Our Annual Pro Sale. View Details »

Seven at one blow – New & polished features in Scalaz 7

Lars Hupel
February 08, 2013

Seven at one blow – New & polished features in Scalaz 7

My talk at the Northeast Scala Symposium 2013, featuring: À-la-carte implicits, Unapply, Law checking, Type-level programming, and Community involvement.

Slides are prepared with LaTeX beamer/XeLaTeX, fonts: Roboto and DejaVu Sans Mono, code highlighting: minted/pygments.

Lars Hupel

February 08, 2013
Tweet

More Decks by Lars Hupel

Other Decks in Programming

Transcript

  1. Seven at one blow
    New & polished features in Scalaz 7
    Lars Hupel
    Februrary 8th, 2013

    View Slide

  2. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    About @larsr h
    ▶ studies Computer Science
    ▶ first contribution December 2011
    ▶ committer since February 2012
    ▶ active (co)maintainer since October 2012
    ▶ did not invent any of the following
    Lars Hupel Seven at one blow Februrary 8th, 2013 2 / 35

    View Slide

  3. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    About Scalaz
    Scalaz is a Scala library for functional programming.
    ▶ purely functional data structures
    ▶ type classes known from Haskell
    ▶ current stable version: 6.0.4
    ▶ successor under development for over a year
    compatible with 2.9.x, 2.10.x (and probably 2.11.x)
    Lars Hupel Seven at one blow Februrary 8th, 2013 3 / 35

    View Slide

  4. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    À-la-carte implicits
    Unapply
    Laws
    Type-level programming
    Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 4 / 35

    View Slide

  5. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    À-la-carte implicits
    Unapply
    Laws
    Type-level programming
    Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 5 / 35

    View Slide

  6. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Previously, in Scalaz 6
    all-you-can-eat object provides most of the implicits
    Lars Hupel Seven at one blow Februrary 8th, 2013 6 / 35

    View Slide

  7. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Previously, in Scalaz 6
    Example
    // import everything
    import scalaz._
    import Scalaz._
    // get all instances
    implicitly[Monad[Option]]
    // get all syntax
    (10.some |@| none) { (_: Int) |+| (_: Int) }
    Lars Hupel Seven at one blow Februrary 8th, 2013 7 / 35

    View Slide

  8. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Now, in Scalaz 7
    Distinction between different kinds of implicits
    1. type class instances
    ▶ ... of our own data types
    ▶ ... of standard library types
    2. syntax: infix operators
    ▶ ... for type class instances
    ▶ ... for standard library types
    3. functions on our own data types
    Lars Hupel Seven at one blow Februrary 8th, 2013 8 / 35

    View Slide

  9. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Now, in Scalaz 7
    Example
    import scalaz._
    {
    // import the instance
    import std.option._
    Monad[Option]
    }
    Lars Hupel Seven at one blow Februrary 8th, 2013 9 / 35

    View Slide

  10. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Now, in Scalaz 7
    Example
    import scalaz._
    {
    import std.option._, std.anyVal._
    import syntax.apply._
    import syntax.semigroup._
    import syntax.std.option._
    (10.some |@| none) { (_: Int) |+| (_: Int) }
    }
    Lars Hupel Seven at one blow Februrary 8th, 2013 9 / 35

    View Slide

  11. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Now, in Scalaz 7
    Example
    import scalaz._
    {
    import std.option._, std.anyVal._
    import syntax.all._, syntax.std.all._
    (10.some |@| none) { (_: Int) |+| (_: Int) }
    }
    Lars Hupel Seven at one blow Februrary 8th, 2013 9 / 35

    View Slide

  12. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Why is this better?
    Disadvantages
    ▶ more import statements
    ▶ makes compile-time debugging harder
    Lars Hupel Seven at one blow Februrary 8th, 2013 10 / 35

    View Slide

  13. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Why is this better?
    Advantages
    ▶ you can use syntax, but you don’t have to
    ▶ improves readability of the code
    ▶ makes compile-time debugging easier
    ▶ increases compilation speed
    Lars Hupel Seven at one blow Februrary 8th, 2013 10 / 35

    View Slide

  14. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    À-la-carte implicits
    Unapply
    Laws
    Type-level programming
    Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 11 / 35

    View Slide

  15. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    def f[M[_], A](x: M[A]): M[A] = x
    f { (x: Int) => x }
    Lars Hupel Seven at one blow Februrary 8th, 2013 12 / 35

    View Slide

  16. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    def f[M[_], A](x: M[A]): M[A] = x
    f { (x: Int) => x }
    Prints a type error:
    found : Int => Int
    required: ?M[?A]
    Lars Hupel Seven at one blow Februrary 8th, 2013 12 / 35

    View Slide

  17. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    Candidates
    ▶ M[X] = Int ⇒ X
    ▶ M[X] = X ⇒ Int
    ▶ M[X] = X ⇒ X
    ▶ M[X] = Int ⇒ Int
    ▶ ...
    This is a known limitation (SI-2712).
    Lars Hupel Seven at one blow Februrary 8th, 2013 13 / 35

    View Slide

  18. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    Candidates
    ▶ M[X] = Int ⇒ X
    ▶ M[X] = X ⇒ Int
    ▶ M[X] = X ⇒ X
    ▶ M[X] = Int ⇒ Int
    ▶ ...
    This is a known limitation (SI-2712).
    Lars Hupel Seven at one blow Februrary 8th, 2013 13 / 35

    View Slide

  19. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    Candidates
    ▶ M[X] = Int ⇒ X
    ▶ M[X] = X ⇒ Int
    ▶ M[X] = X ⇒ X
    ▶ M[X] = Int ⇒ Int
    ▶ ...
    This is a known limitation (SI-2712).
    Lars Hupel Seven at one blow Februrary 8th, 2013 13 / 35

    View Slide

  20. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    Candidates
    ▶ M[X] = Int ⇒ X
    ▶ M[X] = X ⇒ Int
    ▶ M[X] = X ⇒ X
    ▶ M[X] = Int ⇒ Int
    ▶ ...
    This is a known limitation (SI-2712).
    Lars Hupel Seven at one blow Februrary 8th, 2013 13 / 35

    View Slide

  21. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    The problem
    Candidates
    ▶ M[X] = Int ⇒ X
    ▶ M[X] = X ⇒ Int
    ▶ M[X] = X ⇒ X
    ▶ M[X] = Int ⇒ Int
    ▶ ...
    This is a known limitation (SI-2712).
    Lars Hupel Seven at one blow Februrary 8th, 2013 13 / 35

    View Slide

  22. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  23. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  24. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  25. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  26. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  27. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  28. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s use math!
    ▶ known as Higher-order unification
    ▶ Scala adds subtyping
    ▶ everything is subtype of Any
    ▶ Any is always well-kinded
    ▶ ambiguous
    ▶ undecidable
    Lars Hupel Seven at one blow Februrary 8th, 2013 14 / 35

    View Slide

  29. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s approximate!
    def f[M[_], A](x: M[A]): M[A] = x
    f { (x: Int) => x }
    A type constructor without a type class is rarely useful.
    Lars Hupel Seven at one blow Februrary 8th, 2013 15 / 35

    View Slide

  30. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Let’s approximate!
    def f[M[_] : Monad, A](x: M[A]): M[B] = ???
    f { (x: Int) => x }
    Now: more information which can guide type inference
    Lars Hupel Seven at one blow Februrary 8th, 2013 15 / 35

    View Slide

  31. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Dependent types to the rescue
    Define a proof object containing:
    ▶ the type constructor M[_]
    ▶ the inner type A
    ▶ the type class instance M[_] : Monad
    ... and have lots of implicits guided by:
    ▶ prioritisation
    ▶ availability of type class instances
    Lars Hupel Seven at one blow Februrary 8th, 2013 16 / 35

    View Slide

  32. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Dependent types to the rescue
    Define a proof object containing:
    ▶ the type constructor M[_]
    ▶ the inner type A
    ▶ the type class instance M[_] : Monad
    ... and have lots of implicits guided by:
    ▶ prioritisation
    ▶ availability of type class instances
    Lars Hupel Seven at one blow Februrary 8th, 2013 16 / 35

    View Slide

  33. Demo

    View Slide

  34. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Does it work?
    Yes!
    ▶ Scalaz 6: conversions for each concrete type
    ▶ now: general mechanism for common shapes
    ▶ in many cases, type parameters can be omitted
    List(1, 2, 3) traverseU { a =>
    State { x: Int => (x + 1, a) }
    }
    Lars Hupel Seven at one blow Februrary 8th, 2013 18 / 35

    View Slide

  35. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Does it work?
    Well, sort of.
    ▶ 500 lines of boilerplate
    ▶ one implicit per type shape (there are infinitely many)
    ▶ compile errors can get a little funky
    ▶ needs dependent types
    Lars Hupel Seven at one blow Februrary 8th, 2013 18 / 35

    View Slide

  36. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    À-la-carte implicits
    Unapply
    Laws
    Type-level programming
    Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 19 / 35

    View Slide

  37. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Contracts
    .
    .
    “ The equals method implements an equivalence relation on non-null
    object references:
    ▶ It is reflexive: for any non-null reference value x,
    x.equals(x) should return true.
    ▶ It is symmetric: for any non-null reference values x and y,
    x.equals(y) should return true if and only if y.equals(x)
    returns true.
    ▶ ...
    Java API: Object#equals .
    .

    Lars Hupel Seven at one blow Februrary 8th, 2013 20 / 35

    View Slide

  38. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Type classes & Lavs
    ▶ type classes abstract over types
    ▶ offer common functionality
    ▶ users expect similar behaviour
    ▶ ... which needs to be formalised
    Lars Hupel Seven at one blow Februrary 8th, 2013 21 / 35

    View Slide

  39. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Type classes & Lavs
    ▶ type classes abstract over types
    ▶ offer common functionality
    ▶ users expect similar behaviour
    ▶ ... which needs to be formalised
    Lars Hupel Seven at one blow Februrary 8th, 2013 21 / 35

    View Slide

  40. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Type classes & Lavs
    ▶ type classes abstract over types
    ▶ offer common functionality
    ▶ users expect similar behaviour
    ▶ ... which needs to be formalised
    Lars Hupel Seven at one blow Februrary 8th, 2013 21 / 35

    View Slide

  41. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Legal problems
    .
    .
    “ I have a legal question: Is this a lawful monoid to you?
    Tony Morris .
    .

    Lars Hupel Seven at one blow Februrary 8th, 2013 22 / 35

    View Slide

  42. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Laws in Scalaz
    ▶ embedded in type classes, mirroring their hierarchy
    ▶ one method per law
    ▶ ScalaCheck tests instances
    ▶ ... by producing random input
    ▶ Not a theorem prover!
    ▶ ... but better than usual unit tests
    ▶ our bindings can be used by other projects
    ▶ 332 occurences of checkAll in our tests
    Lars Hupel Seven at one blow Februrary 8th, 2013 23 / 35

    View Slide

  43. Demo

    View Slide

  44. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    À-la-carte implicits
    Unapply
    Laws
    Type-level programming
    Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 25 / 35

    View Slide

  45. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 26 / 35

    View Slide

  46. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    It’s in the types
    Scalaz has heterogeneous lists too!
    ▶ ... but not as general as in Shapeless
    ▶ used for:
    ▶ Applicative syntax
    ▶ String formatting
    ▶ type class composition
    Lars Hupel Seven at one blow Februrary 8th, 2013 27 / 35

    View Slide

  47. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Heterogeneous lists
    Everybody loves tuples.
    ▶ fixed arity, different element types
    ▶ maximum arity 22, one class per arity
    ▶ but: no useful manipulations (reverse, append, access, ...)
    Lars Hupel Seven at one blow Februrary 8th, 2013 28 / 35

    View Slide

  48. Demo

    View Slide

  49. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    À-la-carte implicits
    Unapply
    Laws
    Type-level programming
    Community involvement
    Lars Hupel Seven at one blow Februrary 8th, 2013 30 / 35

    View Slide

  50. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    What happened in the past year?
    We got tons of contributions (≈ 200 issues & pull requests).
    ▶ folding non-empty data structures
    ▶ Lens families
    ▶ documentation & test fixes
    ▶ interoperability with other libraries
    ▶ new data types
    ▶ less lawless classes
    ▶ ...
    Lars Hupel Seven at one blow Februrary 8th, 2013 31 / 35

    View Slide

  51. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    Validation DSL
    check(”123456789012345”).
    checkThat(strLength(16, ”wrong length”)).
    checkThat(luhn(”wrong checksum”)).
    convertTo(int(”not an integer”)).
    toValidation
    // Result:
    // Failure(NonEmptyList(wrong length, wrong checksum))
    Lars Hupel Seven at one blow Februrary 8th, 2013 32 / 35

    View Slide

  52. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    What can you do?
    ... if you’re using Scalaz 6
    ▶ migrate to the latest milestone
    ▶ Tell us about it!
    ... if you’re not using Scalaz
    ▶ adopt Scalaz 7
    ▶ Ask questions!
    Lars Hupel Seven at one blow Februrary 8th, 2013 33 / 35

    View Slide

  53. À-la-carte implicits Unapply Laws Type-level programming Community involvement
    What are we going to do?
    ▶ release 7.0.0-final soon ... probably this year
    ▶ not break too much until then
    ▶ stay binary compatible in the 7.0.x series
    ▶ revamp our web site(s)
    Lars Hupel Seven at one blow Februrary 8th, 2013 34 / 35

    View Slide

  54. Q & A
    larsrh.github.com
    @larsr h

    View Slide