This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| trait Shape[A] { | |
| def area(a: A): Double | |
| } | |
| case class Circle(radius: Double) | |
| case class Rectangle(width: Double, length: Double) | |
| // Here > | |
| implicit object CircleShape extends Shape[Circle] { | |
| override def area(circle: Circle) : Double = math.Pi * math.pow(circle.radius, 2) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // vvvvvvvvvvvv (new parameter) | |
| def areaOf[A](shapeInfo: A, shape: Shape[A]): Double = shape.area(shapeInfo) | |
| areaOf(Circle(10), new CircleShape) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| trait Shape { | |
| def area: Double | |
| def info: String | |
| } | |
| class Circle(radius: Double) extends Shape { | |
| override def area: Double = math.Pi * math.pow(radius, 2) | |
| override def info: String = s"Hi, I'm a circle with radius $radius" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| trait Shape { | |
| def area: Double | |
| } | |
| trait Printable { | |
| def info: String | |
| } | |
| class Circle(radius: Double) extends Shape with Printable { | |
| override def area: Double = math.Pi * math.pow(radius, 2) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| val lazyOption: LazyFunctor[Option, Int] = toLazyFunctor(Some(42)) | |
| val transformed: LazyFunctor[Option, Int] = lazyOption.map(_ + 1).map(_ + 2) // silly example | |
| // nothing is executed yet | |
| // apply all transformations at once, yields Some(45) | |
| val option: Option[Int] = fromLazyFunctor(transformed) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| sealed trait LazyFunctor[F[_], A] { | |
| // takes a function and applies it to original value | |
| def transformation[B](f: A => B): F[B] | |
| // interace 'map' to be used as functor | |
| def map[B](f: A => B): LazyFunctor[F, B] = ??? | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // lets also make it an abstrac class and add self type annotation | |
| abstract class LazyFunctor[F[_], A] { self => | |
| // function to be applied when we call "run" | |
| def transformation[B](f: A => B): F[B] | |
| // interace 'map' to be used as functor | |
| def map[B](f: A => B): LazyFunctor[F, B] = new LazyFunctor[F, B] { | |
| def transformation[C](g: B => C): F[C] = self.transformation(g compose f) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| abstract class LazyFunctor[F[_], A] { self => | |
| // should be implemented as a composition of transformations | |
| def transformation[B](f: A => B): F[B] | |
| // apply transformations and get our value back | |
| def run: F[A] = transformation(identity) | |
| // interace 'map' to be used as functor | |
| def map[B](f: A => B): LazyFunctor[F, B] = new LazyFunctor[F, B] { | |
| def transformation[C](g: B => C): F[C] = self.transformation(g compose f) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| def toLazyFunctor[F[_], A](fa: F[A]): LazyFunctor[F, A] = ??? | |
| def fromLazyFunctor[F[_], A](lf: LazyFunctor[F, A]): F[A] = lf.run |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // vvvvvvvvvvvvvvvvvvvvvv | |
| def toLazyFunctor[F[_], A](fa: F[A])(implicit F: Functor[F]): LazyFunctor[F, A] = | |
| new LazyFunctor[F, A] { | |
| override def transformation[B](f: (A) => B): F[B] = F.map(fa)(f) | |
| } | |
| def fromLazyFunctor[F[_], A](lf: LazyFunctor[F, A]): F[A] = lf.run |