juan_gandhi: (Default)
(that's scala)

  /**
   * Builds a category out of a segment of integers between 0 and n (not included).
   *
   * @param n number of elements
   * @return a new category
   */
  implicit def segment(n:Int) : Category[Int, (Int, Int)] = Category(PoSet.range(0, n, 1))
//...

  def testImplicitSegment {
    def sut: Category[Int, (Int, Int)] = 3
    assertEquals(_3_, sut)
  }

now imagine

Sep. 7th, 2010 02:10 pm
juan_gandhi: (Default)
I badly need flatMap in my java code...
juan_gandhi: (Default)

scala> abstract class N[T]                                                                                                                  
defined class N

scala> case class L[T](v:T) extends N[T]                                                                                 
defined class L

scala> case class B[T](kids:List[N[T]]) extends N[T]                                                                     
defined class B

scala> val t = B(List(B(List(L("ab"),L("cd"),B(List(L("xy"),L("z"))))),L("middle")))                                                        
t: B[java.lang.String] = B(List(B(List(L(ab), L(cd), B(List(L(xy), L(z))))), L(middle)))

scala> def scan[T](tree:N[T]):List[T] = tree match { case L(v) => List(v); case B(kids) => kids flatMap (scan(_)) } 
scan: [T](N[T])List[T]

scala> scan(t)                                                                                                                 
res17: List[java.lang.String] = List(ab, cd, xy, z, middle)

scala> 


I used repl, so it's kind of too laconic; in real life you probaly won't call your class N, L and B. But you know what I mean, right?
juan_gandhi: (Default)
It's just pattern matching + monadic lifting. Omg. The problem was in language.[livejournal.com profile] kouzdra was right, all these patterns are just a set of dirty tricks that are good only when our language language is too bad.
juan_gandhi: (Default)
  def product[X, T[_] <: Iterable[_]](xss:T[Set[X]]): Set[T[X]] =
      if (xss.isEmpty) {
        Set(T())
      } else {
        product(xss.first, xss.tail) map cat
      }


Not sure if it'll work. What happens here, we take type T, which is at least an Iterable, and build a product of T of sets; so it will be a set of Ts (kind of like monadic transformer, no? To me, it is a commutator), Set.T -> T.S; what I need from T is an empty constructor and a cat.

Will see.
juan_gandhi: (Default)
(pls don't laugh)

So, really, in Java we cannot declare Functor, like in Scala?

trait Functor[F[_]] {
  def fmap[A, B](r: F[A], f: A => B): F[B]
}
juan_gandhi: (Default)
I was experimenting with Set[T] functor variance. Here are my considerations regarding the opportunity to make it contravariant. In short: it's impossible.

    /**
     * Casts a set into a set of subtype (contravariance, that is)
     * This method does not work, due to JVM type erasure.
     * Actually, delegating the work to runtime would be a stupid idea anyway;
     * so, is it a general problem with oop? Have to think.
     */
    @Deprecated  
    /*implicit*/ def downshift[A, B >: A] (source: Set[B]) : Set[A] = {
      val b2a: (B => A) = {case (a: A) => a}
      val elements = {for (b <- source; if b.isInstanceOf[A]) yield b2a(b)}
      setOf(elements, source.size, source.contains _)
    }


So, what I am thinking. Can we make Set functor contravariant in OOP? I mean, we have two problems here:

  1. Java type erasure makes it impossible to actually check the element type;

  2. OOP in general forces us to delegate this type checking to runtime - which is, I assume, a wrong idea



Seems like variance just does not work here.

I'll continue investigating the opportunities for covariance.
juan_gandhi: (Default)
Last night I've managed to write a class LazyPair where x is fixed and y is lazily calculated, via a given function.

Then I started thinking about variance. It is positive on y, but how about x? It is not so for x, since we have a function, and its argument should have negative variance. But I wrote in LazyPair definition that it implements Product2, that is, I'm saying it is "something like" a Cartesian product. So. If it is a Cartesian product, it should be covariant on both arguments.

So, whad do we have, given X and YX, and, of couse, we have X×YX → X×Y - but it is not a natural transformation. In short, bad luck. No functoriality. So I probably have to throw away the idea of lazy pair.

So there's a question regarding an adequate categorical interpretation of caching in general. I kind of can't figure out, how to deal with it.

In my specific case, in my code, I'll be replacing LazyPair[X, Y] with (X, X=>Y) (this means X×YX in Scala). But then thunk disappears. Something is wrong here.

Upd: thank you, [livejournal.com profile] huzhepidarasa! Got this stuff working:
  test("lazy pair should be covariant in first parameter") {
    val p: Product2[Int, Int] = LazyPair(123, (x:Int) => x * x)
    val q: Product2[Any, Int] = p
    expect(123) {q._1}
  }

  test("lazy pair should be covariant in second parameter") {
    val p: Product2[Int, Int] = LazyPair(8, (x:Int) => x * x)
    val q: Product2[Int, Any] = p
    expect(64) {q._2}
  }

  test("lazy pair assignment does not involve evaluation") {
    var n = 0;
    val p: Product2[Int, Int] = LazyPair(8, (x:Int) => {n = n + 1; x * x})
    expect(0){n}
    val q: Product2[Int, Any] = p
    expect(0){n}
    expect(64) {q._2}
    expect(1){n}
  }


(and thank you Martin for removing < from Scala!)
juan_gandhi: (Default)
  case class LazyPair[X, Y](_1: X, f: X => Y) extends Product2[X, Y]
  {
    private lazy val y = f(_1)
    override def toString() = "(" + _1 + "," + _2 + ")"
    override def _2 = y
  }

  def lazyPair[X, Y](x: X, f: X => Y): Product2[X, Y] = new LazyPair(x, f)



The idea is, we won't call the function until we actually need it; and do it only once.

Note there's no variance in type parameters. I really do not know what to do about it, since the right variance would be [-X,+Y], and it does look stupid, no? Or maybe it does not.

Since it is case class, basically that's all we need.

Scala class Pair is actually Tuple2 which has tons of methods. I've lately came to a conclusion that we do not need most of the methods in most of the classes - e.g. Set[T] does not need size... and many other methods. Only have the right stuff.

Well, whatever. Just asking for your opinion.
juan_gandhi: (Default)
scalar !!~ ((for(s <- "Hello Distributed World".split(' ')) yield(()=>println("***"+s+"***"))) 


Что тут происходит:
Берём строку, разбиваем её на подстроки, и для каждой подстроки возвращаем функцию без параметров, которая эту строку печатает на stdout, завернув в звёздочки.

Это всё действие не происходит так уж сразу, а оформляется как поток - когда попросили, тогда и вернули очередную функцию (монада, для понимающих).

Весь этот источник функций привинчивается оператором !!~ (по мне так было бы достаточно взять map) к scalar, представителю распределённой системы gridgain, который рассылает функции узлам, где попало, может быть, в разных уголках нашей маленькой планеты, где они гордо печатают свои тексты. Ну пример такой, вы ж понимаете.

Вчера всё это демонстрировал Никита Иванов на eBig, в ужасном Окленде.

А потом собравшиеся жжюзеры, [livejournal.com profile] _navi_, [livejournal.com profile] chrobin, я грешный, и некто Женя, жж не имеющий, ели в корейской барбекью - т.к. мы все опоздали на пиццу перед лекцией.

(А потом полчаса огородами пытались выехать из Окленда по алгоритму моего навигатора, слишком хорошо мне знакомому, т.к. я месяц отлаживал его аналог у себя на машине, пытаясь понять, на хрена вроде бы приличный многоуровневый двусторонний Дийкстра строит такой дебильный маршрут. Видно, это Окленд наводит порчу. Например, из Бони Дуна в Лос Гатос тот алгоритм вообще дорогу не находит.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

December 2025

S M T W T F S
  123456
78910111213
14151617181920
21222324252627
28293031   

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 1st, 2025 01:17 pm
Powered by Dreamwidth Studios