Entry tags:
Entry tags:
two variances in Scala
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?Entry tags:
so
You know the stupid problem with Java/Scala collections: their
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
Questions? :)
I think it's cool; category theory applied directly to solve a code design problem.
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.
Entry tags:
монада из двух сопряженных функторов
Тут мы с
sassa_nf обсуждали вопрос, как это получается, что оно монада.
В принципе, это есть в МакЛейне, но у МакЛейна всё так мудрено. А надо-то на пальцах.
В другом месте - т.наз. функторы Hom участвуют - а у меня к ним прямо гомофобия; такую неприязнь чувствую к функтору Hom, кушать не могу.
Так вот, напишу-ка я тут вкрадце, шо за сопряженные функторы и как они связаны с монадой.
Для программистов напишу, так что никаких когомологий, кобордизмов, 2-категорий, расширений Кана, а всё на пальцах, лишь бы не лень читать было.
( Read more... )
В принципе, это есть в МакЛейне, но у МакЛейна всё так мудрено. А надо-то на пальцах.
В другом месте - т.наз. функторы Hom участвуют - а у меня к ним прямо гомофобия; такую неприязнь чувствую к функтору Hom, кушать не могу.
Так вот, напишу-ка я тут вкрадце, шо за сопряженные функторы и как они связаны с монадой.
Для программистов напишу, так что никаких когомологий, кобордизмов, 2-категорий, расширений Кана, а всё на пальцах, лишь бы не лень читать было.
( Read more... )
Entry tags:
Oleg Kiselyov explains why not Order extends Equals
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".
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".
