so

Jul. 24th, 2013 09:37 pm
juan_gandhi: (VP)
[personal profile] juan_gandhi
You know the stupid problem with Java/Scala collections: their contains() method takes any type; the explanation being that for this method to be type-dependent, we need contravariance, while collections are (mostly) covariant. So there.

Well, a natural transformation from a covariant functor to a contravariant is not only possible, it's a relatively popular thing. So, does it mean we can make contains() method type-dependent? The answer is YES!

  trait MyList[+T] { // declare a simple collection, e.g. list; it is covariant
    def head:T
    def tail:MyList[T]
    def ::[U>:T](x:U) = HeadAndTail(x, this)
    def size: Int
  }

  case object EmptyList extends MyList[Nothing] { // it's okay that it's a list of Nothing
    def head = error("This list is empty")
    def tail = error("this list is empty")
    def size = 0
  }

  case class HeadAndTail[T](head:T, tail: MyList[T]) extends MyList[T] {
    def size = 1 + tail.size
  }
// All the stuff above allows us to treat lists in a covariant way, like this:
      case class A(name: String) {override def toString = "A(" + name + ")"}
      case class B(override val name: String) extends A(name) {override def toString = "B(" + name + ")"}

      val listB = B("1") :: B("2") :: EmptyList
      listB.size must_== 2
      val listA = A("3") :: listB
      listA.size must_== 3
      val listC: MyList[Any] = listA
// See, MyList is covariant, so if B is a subtype of A, List[B] is a subtype of List[A]

And now... introduce a contravariant trait:
  
  trait Container[-T] {
    def contains(t:T): Boolean
  }

// and the natural transformation from MyList[+T] to Container[-T]:

  implicit def asContainer[T](list:MyList[T]): Container[T] = new Container[T] {
    def contains(t:T) = list.size > 0 && (list.head == t || asContainer(list.tail).contains(t))
  }

And it works. I can draw the appropriate commutative diagrams later, if it is not obvious.

      listA contains A("3") must beTrue
      listA contains B("1") must beTrue
//      listA contains "abracadabra" is a compilation error
      listC contains "abracadabra" must beFalse
      listC contains B("2") must beTrue



Questions? :)

I think it's cool; category theory applied directly to solve a code design problem.
This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

June 2025

S M T W T F S
1 2345 6 7
8 9 10 11 121314
15161718 1920 21
22232425262728
2930     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 23rd, 2025 01:50 pm
Powered by Dreamwidth Studios