 
  
 class Foo {
  val name: String = "foo"
  def print = println(s"I am $name")
}trait Vendor {
  val ids: Set[Int]
  val name: String
}String's and Int'sint, long, double, floata + b == b + a// Type of types
trait Numeric[A] {
  // Operation:
  def add(x: A, y: A): A
}
// Rule:
numeric.add(5, 1) mustEqual numeric.add(1, 5)Numeric?A, where A is able to be added// Valid
val Int = new Numeric[Int] {
  def add(x: Int, y: Int) = x + y
}
val Double = new Numeric[Double] {
  def add(x: Double, y: Double) = x + y
}
// Not Valid
val String = new Numeric[String] {
  def add(x: String, y: String) = x + y
}Numeric is a way to categorize type:a and b, return a appended to btrait Example[A] {
  def append(x: A, y: A): A
  def identity: A
}trait Monoid[A] {
  def mappend(x: A, y: A): A
  def mzero: A
}val String = new Monoid[String] {
  def mappend(x: String, y: String) = x.append(y)
  def mzero = ""
}
val Int = new Monoid[Int] {
  def mappend(x: Int, y: Int) = x + y
  def mzero = 0
}trait Foo[A]<1> {
  def op<2>(arg: A<3>): A<4>
}Seq) as a type -- which it is -- but it's really a type of types, an algebraic structureSeqtrait Functor[A] {
  def map(f: A => B): Functor[B]
}A and returns BFunctor of type Btrait Functor[A] {
  def map(f: A => B<1>): Functor[B]<2>
}var Foo = function(value) {
  this.value = value;
}
Foo.prototype.map = function(f) { // where f is A => B
  return new Foo(f(value));
};Seq is a Functorval s: Seq[Int] = Seq(1, 2, 3)
val s2 = s.map(_.toString)
// s2.type == Seq[String]Array is a Functorvar s = [1, 2, 3];
var s2 = s.map(function(x) { return x.toString(); });
// ["1", "2", "3"]Option is a Functorval o: Option[Int] = Some(10)
val o2 = o.map(_.toString)
// o2.type == Option[String]Future is a Functorval f: Future[PoiLike] = PlaceService.getPlace(1234)
val f2 = s.map(_.mqId)
// f2.type == Future[Int]var p = $.get("/api/place/1234");
var p2 = p.pipe(function(json) {
  return json.name;
});Promise.pipe == Functor.mapfmap always returns a new Functor of B, however the behavior of when fmap "applies" can varry.sealed trait Option[A] extends Functor[A]
case class Some[A](protected val value: A) extends Option[A] {
  val map(f: A => B) = Some(f(value))
}
case object None[A] extends Option[A] {
  val map(f: A => B) = this
}val o: Option[String] = Some("hello")
o.map(_.toUpperCase)
// Some("HELLO")
val o2: Option[String] = None
o2.map(_.toUpperCase)
// NoneFunctor[Functor[A]]?trait AddressLike(
  country: String,
  region: Option[String] = None,
  locality: Option[String] = None,
  ...
)val cityAndState = address.locality.map { city =>
  address.region.map { state =>
    city + ", " + state
  }
}cityAndState?Option[Option[String]]val cityAndState = address.locality.map { city =>
  address.region.map { state =>
    city + ", " + state
  }
}val cs1 = address.locality.map { city =>
  address.region.map { state =>
    city + ", " + state
  }
}
val cs2 = cs1.flatten
// cs1.type == Option[Option[String]]
// cs2.type == Option[String]flatMap is a shortcut for map+map+flattenval cs1 = address.locality.flatMap { city =>
  address.region.map { state =>
    city + ", " + state
  }
}
// cs1.type == Option[String]Option[Option[String]]flatMap is technically part of a Monad which itself is a Functorfor/yield is another way of writing chained flatMap'sval o1 = Some("a")
val o2 = Some("b")
val o3 = Some("c")o1.flatMap { a =>
  o2.flatMap { b =>
    o3.map { c =>
      a + b + c
    }
  }
}for {
  a <- o1
  b <- o2
  c <- o3
} yield a + b + cflatten and flatMap are available on all Functors in Scalamap applies the given function f returning not the result of f, but a new Future such that when the value eventually resolves, f will be applied to itclass PlaceController extends Controller {
  def place(id: String) = Action.async {
    val futurePlace: Future[PlaceLike] = PlaceService.getPlace(id)
    futurePlace.map { place =>
      Ok(views.html.place(place))
    }
  }
}futurePlace.map { place=> Ok(views.html.place(place) ...?onSuccess and onFailure?class Future[U] {
  def onSuccess[U](pf: PartialFunction[T, U]): Unit
  def onFailure[U](pf: PartialFunction[T, U]): Unit
}UnitonSuccess and onFailure mutate the Future, providing it a partial function that will be called when the future resolves.
They do not return a new Future.
They are not Functor-like.
map only applies to when the future succeeds, how do we get back a new Functor when it fails?recoverdef get: Action[AnyContent] = Action.async { request =>
  val p = Promise[SimpleResult]()
  val f = fetchUserState(request.cookies)
  f map {
    ...
  }
  f onFailure {
    case e => Logger error("Recently viewed: " + e.getMessage)
  }
  f recover {
    case _ => p success Ok
  }
  p future
}def get: Action[AnyContent] = Action.async { request =>
  fetchUserState(request.cookies)
    .map { ... }
    .recover { case e =>
      Logger.error("Recently viewed: " + e.getMessage)
      Ok
    }
}.getOrElse on Option's is stupidNoneimplicit object StringMonoid extends Monoid[String] {
  def mappend(x: String, y: String) = x + y
  def mzero = ""
}
implicit def safeValue[A](opt: Option[A])(implicit md: Monoid[A]): A =
  opt.getOrElse(md.mzero)
val some: Option[String] = Some("asdf")
val none: Option[String] = None
println(some.toUpperCase + none.toUpperCase)
> "ASDF"
Seq based on a conditional.val s = Seq.empty
if (cond1) s = s ++ Seq(value1) else s
if (cond2) s = s ++ Seq(value1) else s
if (cond3) s = s ++ Seq(value1) else simplicit class SeqOps[A](s: Seq[A]) {
  def when(cond: => Boolean)(value: A) =
    if(cond) s ++ Seq(value) else s
  def unless(cond: => Boolean)(value: A) =
    when(!cond)(value)
  def always(value: A) = when(true)(value)
}val widgets = Seq.empty
  .unless(place.isInstanceOf[BizlocHotel]) { BookingWidget(...) }
  .when(place.isInstanceOf[PoiLike])       { CategoryWidget(...) }
  .when(place.isInstanceOf[AirportLike])   { DelaysWidget(...) }
  .always                                  { RecentlyViewedWidget(...) }s ++ Seq(value) is really Monoid AppendSeq.empty is really Monoid Identityimplicit class MonoidOps[A](origin: A) {
  def when(cond: => Boolean)(value: A)(implicit md: Monoid[A]) =
    if(cond) md.mappend(origin, value) else origin
  def unless(cond: => Boolean)(value: A)(implicit md: Monoid[A]) =
    when(!cond)(value)
  def always(value: A)(implicit md: Monoid[A]) =
    when(true)(value)
}def cityName(city: LocalityLike) = 
  city.locality
    .when(city.country == "US") { city.region }Stringtrait FromString[A] {
  def fromString(value: String): A
}def cityName[A](city: LocalityLike)(implicit md: Monoid[A], fs: FromString[A]) = 
  md.mzero
    .always(fs.fromString(city.locality))
    .when(city.country == "US") { fs.fromString(city.region) }cityName[String](place)
// Or
cityName[Html](place)
// Or event
cityName[Seq[String]](place)