Archive for February, 2010

Understanding Haskell interact

Wednesday, February 24th, 2010

There is a function in Haskell’s standard library called interact. It has this type interact :: (String -> String) -> IO ().

Here is the same function in Java:

import java.io.Console;
 
interface Stringer {
  String convertString(String s);
}
 
class Interact {
  // interact :: (String -> String) -> IO ()
  static void interact(Stringer s) {
    final String line = System.console().readLine();
    final String c = s.convertString(line);
    System.out.println(c);
    interact(s);
  }
}

There are some slight differences between the two:

  • In Java, we have had to give a name to the higher-order function (Stringer) with a single method which we have also named (convertString).
  • In Java, we have no guarantee that the implementation of Stringer that is passed to interact is deterministic. In other words, it might perform side-effects and we have no machine-checked guarantee that it will not.

The other major difference is with respect to the evaluation of the arguments. Haskell is call-by-need by default while Java is eagerly evaluated by force. This doesn’t have an impact on understanding the general purpose of Haskell’s interact function by looking at the same function in Java.

That is all. Hope it helps.

Linq has nothing to do with SQL or enumerable lists

Friday, February 19th, 2010

There seems to be quite a lot of misunderstanding of Linq. I am not sure how widespread this misunderstanding is, but if I can be persuaded that my selection sample extrapolates accurately, I might consider expanding on this fact:

Linq has nothing to do with SQL or enumerable lists. Nothing and also, not a single thing.

If this is contentious, please let me know and I will endeavour to do something about it (I already have, so I’ll just refer on to begin with).

SKI combinator calculus in Java

Monday, February 8th, 2010
interface Lam<X, Y> {
  Y apply(X x);
}
 
// http://en.wikipedia.org/wiki/SKI_combinator_calculus
class SKI {
  public static <A, B, C> Lam<Lam<A, Lam<B, C>>, Lam<Lam<A, B>, Lam<A, C>>> s() {
    return new Lam<Lam<A, Lam<B, C>>, Lam<Lam<A, B>, Lam<A, C>>>() {
      public Lam<Lam<A, B>, Lam<A, C>> apply(final Lam<A, Lam<B, C>> f) {
        return new Lam<Lam<A, B>, Lam<A, C>>() {
          public Lam<A, C> apply(final Lam<A, B> g) {
            return new Lam<A, C>() {
              public C apply(final A a) {
                return f.apply(a).apply(g.apply(a));
              }
            };
          }
        };
      }
    };
  }
 
  public static <A, B> Lam<A, Lam<B, A>> k() {
    return new Lam<A, Lam<B, A>>() {
      public Lam<B, A> apply(final A a) {
        return new Lam<B, A>() {
          public A apply(final B b) {
            return a;
          }
        };
      }
    };
  }
 
  public static <A> Lam<A, A> i() {
    return SKI.<A, Lam<A, A>, A>s().apply(SKI.<A, Lam<A, A>>k()).apply(SKI.<A, A>k());
  }
}

Scala exercise

Saturday, February 6th, 2010

A result of a discussion in the #scala IRC channel.

Write a minimum function that works on Array[String] and List[Int]. (see error("todo"))

trait Foldable[-F[_]] {
  def foldl[A, B](f: (A, B) => A, a: A, as: F[B]): A
 
  def reducel[A](f: (A, A) => A, as: F[A]): Option[A] = foldl[Option[A], A]((a1, a2) => 
    Some(a1 match {
      case None => a2
      case Some(x) => f(a2, x)
    }), None, as)
}
 
object Foldable {
  val ListFoldable = new Foldable[List] {
    def foldl[A, B](f: (A, B) => A, a: A, as: List[B]) =
      as.foldLeft(a)(f)
  }
 
  val ArrayFoldable = new Foldable[Array] {
    def foldl[A, B](f: (A, B) => A, a: A, as: Array[B]) =
      as.foldLeft(a)(f)
  }
}
 
sealed trait Ordering
case object LT extends Ordering
case object EQ extends Ordering
case object GT extends Ordering
 
// contra
trait Order[A] {
  def compare(a1: A, a2: A): Ordering
 
  def min(a1: A, a2: A) =
    if(compare(a1, a2) == LT) a1 else a2
}
 
object Order {
  def order[A](f: (A, A) => Ordering): Order[A] = new Order[A] {
    def compare(a1: A, a2: A) = f(a1, a2)
  }
 
  val IntOrder = order[Int]((a1, a2) => 
    if(a1 > a2) GT
    else if(a1 < a2) LT
    else EQ)
 
  val StringOrder = order[String]((a1, a2) =>
    if(a1 > a2) GT
    else if(a1 < a2) LT
    else EQ)
}
 
object Main {
  import Foldable._
  import Order._
 
  def minimum[F[_], A](as: F[A], order: Order[A], fold: Foldable[F]) =
    // Zm9sZC5yZWR1Y2VsW0FdKChhLCBiKSA9PiBvcmRlci5taW4oYSwgYiksIGFzKQ==
    error("todo")
 
  def main(args: Array[String]) {
    val i = minimum(args, StringOrder, ArrayFoldable)
    println(i)
 
    val j = minimum(List(5, 8, 2, 9), IntOrder, ListFoldable)
    println(j)    
  }
}

Functional Java 2.21

Friday, February 5th, 2010

Includes a number of bug fixes and an immutable 2-3 finger tree for sequences supporting access to the ends in amortized O(1) time.