juan_gandhi: (VP)
монады в скале и все такое

Добавить/поправить/расширить что, или как?
juan_gandhi: (VP)
scala> val s = Set("a", "b", "c")
s: scala.collection.immutable.Set[String] = Set(a, b, c)

scala> val t = s.map(_ + ":)")
t: scala.collection.immutable.Set[String] = Set(a:), b:), c:))

scala> val s = Set("a1", "a2", "a3")
s: scala.collection.immutable.Set[String] = Set(a1, a2, a3)

scala> val t = s.map(_ take 1)
t: scala.collection.immutable.Set[String] = Set(a)

scala> val u:Set[Any] = s map identity
u: Set[Any] = Set(a1, a2, a3)

scala> val v:Set[Any] = s
<console>:8: error: type mismatch;
 found   : scala.collection.immutable.Set[String]
 required: Set[Any]
Note: String <: Any, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
       val v:Set[Any] = s

From a categorist's p.o.v, wtf, if we have map, we have a covariant functor. But wow, it's "type theory", covariance here means only covariance w.r.t. subtyping. So, big deal, map with identity, no? I mean, not being a typist, I don't even understand the problem. Do you?


Jul. 24th, 2013 09:37 pm
juan_gandhi: (VP)
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.
juan_gandhi: (Default)
Тут мы с [livejournal.com profile] sassa_nf обсуждали вопрос, как это получается, что оно монада.

В принципе, это есть в МакЛейне, но у МакЛейна всё так мудрено. А надо-то на пальцах.

В другом месте - т.наз. функторы Hom участвуют - а у меня к ним прямо гомофобия; такую неприязнь чувствую к функтору Hom, кушать не могу.

Так вот, напишу-ка я тут вкрадце, шо за сопряженные функторы и как они связаны с монадой.
Для программистов напишу, так что никаких когомологий, кобордизмов, 2-категорий, расширений Кана, а всё на пальцах, лишь бы не лень читать было.
Read more... )
juan_gandhi: (Default)
Subclassing errors, OPP, and practically checkable rules to prevent them

P.S. I believe the problem is that with stateful objects, we do not know exactly which category are we dealing with; roughly speaking, for class A subclassing class B, there are actually two monads, with a natural transformation from one to another; and we think we have a functor from, not sure yet, one Kleisli category to another, or from one Eilenberg-Moore category to another, or even an interesting relationship between two categories of adjoints generated by the monads.

Have to look closer; maybe this explains the problem with "Liskov substitution".


juan_gandhi: (Default)

February 2017

    1 2 3 4
5 6 7 8 9 10 11
1213 14 15 16 17 18
19 20 21 22 2324 25


RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 27th, 2017 04:32 am
Powered by Dreamwidth Studios