Thinking in Scala - Scala Patterns Pub Share

If you're new to scala, here are some specific patterns.

Cake pattern

The cake pattern is the quintesential scala pattern made possible by traits as opposed to interfaces: link.

Pimping with implicits

Pimping is adding methods to another class, by essentially definiting an implicit cast to a new type which defines that method. The compiler will automatically use the implicit cast when the method is used.

Benefits are many, including no dependency on the base class, no poluting of the name space (at least no visible or known to the user) etc. This is related to:

Read the original article

Quite possibly the best example for this in the scala libraries is adding the functional methods to the Java collections:

import scala.collection.JavaConversions._

val resp = new java.util.ArrayList()
...
resp.filter ( _.contains("ahoi") ).size

Type classes

Type classes are a concept explored originally in Haskell and provides a different kind of polymorphism than usual strait-up OO class inheritance.

To attempt to briefly introduce the pattern: instead of inheriting a trait or interface, the respective functionality is defined as a type class and implementations are provided for the different subsequent types. The compiler then figures out which implementation to use in different contexts, transparent to the client code.

Scala permits the same pattern, via a mix of traits, modules (for scoping), together with implicits and associated context bounds etc. These are some of the good articles on the subject:

  • link nice intro
  • link vs Ruby, with duck typing and monkey patching
  • link vs Haskell
  • OO vs type classes - a Haskell hardcore discussion of type classes contrasted with OO, very good read
  • scalaz intro - good introduction to this pattern, as used in scalaz, video from 5:30

You should read the articles above for a detailed understanding. Here's a simple comparison I derived, for clarity:

//============== the OO version

  trait Eq[A] { // the type trait
    def sameAs(b:A) : Boolean   // so many name clashes with eq/equals etc
  }

  case class Student (name:String) extends Eq[Student] { // classic OO implementation
    override def sameAs(b:Student) = this.name == b.name
  }

    // someone actually using the Eq: A must be a subtype of Eq
  def member[A <: Eq[A]] (a:A, container:List[A]) = 
    container.exists(_.sameAs(a))

  member (Student("John"), List(Student("John")))

and

    //============== the Type Class version

    trait Eq[A] { // the type trait
      def areTheSame(a: A, b: A): Boolean
    }

    case class Student(name: String) // better decoupling - extends nothing

    object EqImplementations { // the implementations for different classes
      implicit object EqStudent extends Eq[Student] {
        override def areTheSame(a: Student, b: Student) = a.name == b.name
      }
    }

    // all it says is that there must be an Eq implementation for A, somewhere in context
    def member[A: Eq](a: A, container: List[A]) =
      container.exists(implicitly[Eq[A]].areTheSame(_, a))

    import EqImplementations._ // bring it in context

    member(Student("John"), List(Student("John")))

In the second version, the implementation for Eq corresponding to Student is figured out implicitly. The type class version is a little longer but the benefits include decoupling the Student from Eq.


Was this useful?    

By: Razie | 2013-05-24 .. 2016-05-11 | Tags: post , scala , pattern , programming


See more in: Cool Scala Subscribe

Viewed 2569 times ( | History | Print ) this page.

You need to log in to post a comment!