```
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`

's`int`

, `long`

, `double`

, `float`

- Operations
- Rules

`a + 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 addedsuch that x + y == y + x

```
// 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 `b`

```
trait 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 structure`Seq`

```
trait Functor[A] {
def map(f: A => B): Functor[B]
}
```

`A`

and returns `B`

`Functor`

of type `B`

```
trait 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 Functor```
val s: Seq[Int] = Seq(1, 2, 3)
val s2 = s.map(_.toString)
// s2.type == Seq[String]
```

`Array`

is a Functor```
var s = [1, 2, 3];
var s2 = s.map(function(x) { return x.toString(); });
// ["1", "2", "3"]
```

`Option`

is a Functor```
val o: Option[Int] = Some(10)
val o2 = o.map(_.toString)
// o2.type == Option[String]
```

`Future`

is a Functor```
val 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.map`

`fmap`

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)
// None
```

`Functor[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+flatten```
val 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 Functor`for/yield`

is another way of writing chained `flatMap`

's```
val 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 + c
```

`flatten`

and `flatMap`

are available on all Functors in Scala`map`

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 it```
class 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
}
```

`Unit`

`onSuccess`

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?`recover`

```
def 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 stupid`None`

```
implicit 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 s
```

```
implicit 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 Append`Seq.empty`

is really Monoid Identity```
implicit 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 }
```

`String`

```
trait 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)
```