Advertisement
Guest User

Untitled

a guest
Apr 26th, 2015
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.72 KB | None | 0 0
  1. import language.higherKinds
  2.  
  3. // Scala doesn't have Identity, so here....
  4. object Id {
  5. type Identity[+A] = A
  6. implicit val identityFunctor: Functor[Identity] = new Functor[Identity] {
  7. def fmap[A, B](f: A => B)(fa: Identity[A]) = f(fa)
  8. }
  9. }
  10.  
  11. import Id._
  12.  
  13. // Scala doesn't have Functors, so here....
  14. trait Functor[F[_]] {
  15. def fmap[A, B](f: A => B)(m: F[A]): F[B]
  16. }
  17. object Functor {
  18. def apply[A[_]](implicit ev: Functor[A]) = ev
  19. }
  20.  
  21. // Coyoneda definition
  22. sealed trait Coyoneda[F[_], A] {
  23. def map[B](f: A => B): Coyoneda[F, B] = this match {
  24. case Coyo(g, v) => Coyo(f compose g, v)
  25. }
  26. }
  27. case class Coyo[F[_], A, B](run: B => A, f: F[B]) extends Coyoneda[F, A]
  28.  
  29. object Coyoneda {
  30. def liftCoyoneda[F[_], A](f : F[A]): Coyoneda[F, A] =
  31. Coyo((a: A) => a, f)
  32.  
  33. def lowerCoyoneta[F[_]: Functor, A](coyo: Coyoneda[F, A]): F[A] = coyo match {
  34. case Coyo(f, m) => Functor[F].fmap(f)(m)
  35. }
  36.  
  37. // Eraser[A] is just a Coyoneda on identity
  38. type Eraser[A] = Coyoneda[Identity, A]
  39. def runEraser[A](eraser: Eraser[A]): A = lowerCoyoneta(eraser)
  40. }
  41. // Our typeclass
  42. trait Foo[A] {
  43. def foo(a: A): String
  44. }
  45. object Foo {
  46. def apply[A](implicit ev: Foo[A]) = ev
  47.  
  48. def fooCoyo[A: Foo](f: A): Coyoneda.Eraser[String] =
  49. Coyo[Identity, String, A](Foo[A].foo(_: A), f)
  50. }
  51.  
  52. // Our types
  53. case class Bar(run: Int)
  54. object Bar {
  55. implicit val foo: Foo[Bar] = new Foo[Bar] {
  56. def foo(a: Bar) = a.run.toString
  57. }
  58. }
  59. case class Baz(run: String)
  60. object Baz {
  61. implicit val foo: Foo[Baz] = new Foo[Baz] {
  62. def foo(a: Baz) = a.run
  63. }
  64. }
  65.  
  66. object Main {
  67. import Coyoneda._
  68. import Foo.fooCoyo
  69. def main = {
  70. val list: List[Eraser[String]] =
  71. fooCoyo(Bar(1)) :: fooCoyo(Baz("Hello")) :: Nil
  72. list.map(runEraser) // Prints List(1, Hello)
  73. }
  74. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement