# 8 - Implicits

Another powerful Scala feature today.
Implicits do a lot of black magic behind the scenes.
Today we learn how to control the magic.

You can find today's contents here.

## Practice

We'll extend an existing well-known type with a few methods, use implicits to sort collections of our own datatypes and finally try to improve equality operations in Scala.

1. Define the class `RichInteger` that takes an Int parameter:
`class RichInteger(val x: Int)`
• Define the sqrt method on it. It should do the square root of x. Use an implicit conversion from `Int` to `RichInteger` to enable this operation on integers.
• Convert the previous code to an implicit class. How does this help you?
• Add an isPrime method to `RichInteger`. It should check whether x is prime or not.
• Add the `gcd` method to `RichInteger`. It should receive another y parameter of type `Int` and compute the greatest common divisor of the two.
• Test the new magic methods you just created.
2. Define a data type for semantic versioning.
• Use a case class and name it `Version`. It should have 3 fields, all integers: `major`, `minor` and `patch`.
• Define the `<` operator on the new data type.
• Define a value for a `Version` ordering. Its type should be `Ordering[Version]`
`val order: Ordering[Version] = ???`
• Create a list of versions. Try calling the `sorted` method on it. Does it work?
• Promote the ordering defined earlier to an implicit value. What's the recommended place to put the implicit?
3. Define the `Eq` typeclass to offer support for equality testing.
```trait Eq[A] {
def ===(l: A, r: A): Boolean
def =!=(l: A, r: A): Boolean
}```
• The two operations should check for equality. Tip - you can use the existing `==` and `!=` in the actual implementation.
• Typeclasses usually define additional `Ops` traits in order to provide an operator like notation to the implementing types. Use the following companion object for Eq in order to enable `===` and `=!=` on any type class instance.
```object Eq {

def apply[A](implicit instance: Eq[A]): Eq[A] = instance

trait Ops[A] {
def typeClassInstance: Eq[A]
def self: A
def ===(other: A) = typeClassInstance.===(self, other)
def =!=(other: A) = typeClassInstance.=!=(self, other)
}

trait ToEqOps {
implicit def toEqOps[A](target: A)(implicit instance: Eq[A]) = new Ops[A] {
override val typeClassInstance = instance
override val self              = target
}
}

object ops extends ToEqOps
}```
• Define an instance for `Int`s. Use the `Eq` object to define it. Compare two integers using the `===` and `=!=` methods. Does it work for other types as well (e.g. Strings)?
• Define an universal instance that compares generic types. What's the difference between `==` vs. `===` and `!=` vs `=!=`? 