Archive for the 'Programming' Category

Monads do not compose

Thursday, February 24th, 2011

On the Scala mailing list, I said “monads do not compose.” What does this mean exactly? Hopefully the following answers it.

Let us first state the Functor, Applicative and Monad interfaces:

trait Functor[F[_]] {
  def fmap[A, B](f: A => B, a: F[A]): F[B]
}
 
trait Applicative[F[_]] extends Functor[F] {
  def ap[A, B](f: F[A => B], a: F[A]): F[B]
  def point[A](a: A): F[A]
  override final def fmap[A, B](f: A => B, a: F[A]) =
    ap(point(f), a) 
}
 
trait Monad[F[_]] extends Applicative[F] {
  def flatMap[A, B](f: A => F[B], a: F[A]): F[B]
  override final def ap[A, B](f: F[A => B], a: F[A]) =
    flatMap((ff: A => B) => fmap((aa: A) => ff(aa), a), f)
}

Let’s now restate our claims:

  1. Functors compose
  2. Applicatives compose
  3. Monads do not compose

I will now address points 1) and 2). What does it mean for X to compose in this context? Let us now answer that question more succinctly:

It means that we can write a function with this signature (for some X):

def XCompose[M[_], N[_]](implicit mx: X[M], nx: X[N]): 
     X[({type λ[α]=M[N[α]]})#λ]

This return type may look like gobbledy, but it’s just a fancy way of doing partial type constructor application in Scala. It is essentially the X type constructor applied to the composition of M and N and followed by a type variable just like M and N itself (kind * -> *). Let us now test our claims.

Functors compose. That is to say, we can write:

def FunctorCompose[M[_], N[_]]
    (implicit mx: Functor[M], nx: Functor[N]): 
        Functor[({type λ[α]=M[N[α]]})#λ]

Let’s do it!

new Functor[({type λ[α]=M[N[α]]})#λ] {
  def fmap[A, B](f: A => B, a: M[N[A]]) =
      mx.fmap((na: N[A]) => nx.fmap(f, na), a)
}

Here we are composing two Functors. Claim 1) is demonstrated. What about claim 2)? Here we go. Hold your breath!

def ApplicativeCompose[M[_], N[_]]
    (implicit ma: Applicative[M], na: Applicative[N]):
        Applicative[({type λ[α]=M[N[α]]})#λ] =
  new Applicative[({type λ[α]=M[N[α]]})#λ] {
  def ap[A, B](f: M[N[A => B]], a: M[N[A]]) = {
    def liftA2[X, Y, Z](f: X => Y => Z, a: M[X], b: M[Y]): M[Z] =
      ma.ap(ma.fmap(f, a), b)
    liftA2((ff: N[A => B]) => (aa: N[A]) => na.ap(ff, aa), f, a)
  }
  def point[A](a: A) =
    ma point (na point a)
}

Have fun untangling that! It’s a bit noisy but this is mostly because Scala requires a lot of boilerplate. Hopefully you can get to the essence of what it means to compose two Applicative functors.

Now let’s move to Monad. Essentially, I am saying that you won’t be able to write such a function for Monad. I really encourage you to try to write it so you can see the twist that you will get into.

def MonadCompose[M[_], N[_]](implicit ma: Monad[M], na: Monad[N]):
    Monad[({type λ[α]=M[N[α]]})#λ]

Here is a compilable version
http://paste.pocoo.org/show/343606/

Hope that helps!

List with O(1) cons and snoc in Scala

Sunday, February 20th, 2011

A pseudo difference list with constant time prepend (cons) and append (snoc).

There is an efficiency issue with respect to Scala’s TCO implementation (making this data structure untenable?), however, I have forgotten the details of that.

In any case, a finger-tree is often more appropriate, but it would be nice to revive the Endo[List[A]]!

sealed trait DiffList[A] {
  val endo: List[A] => List[A]
 
  import DiffList._
 
  // cons O(1)
  def <::(a: A): DiffList[A] = new DiffList[A] {
    val endo = (z: List[A]) => a :: DiffList.this.endo(z)
  }
 
  // snoc O(1)
  def ::>(a: A): DiffList[A] = new DiffList[A] {
    val endo = (z: List[A]) => DiffList.this.endo(a :: z)
  }
 
  // append O(1)
  def :::>(a: DiffList[A]): DiffList[A] = new DiffList[A] {
    val endo = (z: List[A]) => DiffList.this.endo(a.endo(z))
  }
 
  // O(n)
  def toList = endo(Nil)
}
 
object DiffList {
  def empty[A]: DiffList[A] = new DiffList[A] {
    val endo = (z: List[A]) => z
  }
 
  def single[A](a: A): DiffList[A] = a <:: empty[A]
}

Critique of Odersky’s Scala levels

Monday, January 17th, 2011

Martin Odersky, creator of the Scala programming language, recently wrote a brief article describing levels of Scala expertise. Martin labelled the levels in increasing order: [A1, A2, A3, L1, L2, L3].

I wish to register a small objection here, with recognition of otherwise sound judgement. While the objection is small, I think the consequences of what I believe is an error, are quite detrimental.

I will repost Martin’s specification for L3, the highest:

Level L3: Expert library designer

  • Early initializers
  • Abstract types
  • Implicit definitions
  • Higher-kinded types

First, I will get a couple of nitpicks out of the way. Martin’s L2 specifies that variance annotations will be used at this level. I (we: scalaz) propose that there is another level again, where you come to the realisation that variance annotations are not worth their use in the context of Scala’s limited type-inferencing abilities and other details. Instead, prefer a short-hand version of fmap and contramap functions. Scalaz calls these ∘ and ∙. The details of why this is more appropriate are beside the point here. Nevertheless, Edward Kmett has set out to prove this hypothesis wrong. Many of us have and failed. As far as I know, there is nothing compelling yet but I wish Ed luck with his unique insights.

Second, the suggestion that L3 requires the use of early initializers boggles my mind a little. The idea that these details exist at all is a symptom of a lot of nasty language and interoperability issues. Ultimately, if you are relying on the language-specified initialization order in your library code, then you are doing something disastrously wrong. Long-time users of Scala will recall the number of changes this behaviour went through. There is a gremlin at every turn and (much) more disciplined approaches to library design.

To the point.

If L3 is the highest level attainable, where we are using higher-kinded values and implicits, then what about other levels that are way higher in the level of required understanding? Let’s be clear, the use of these features has been part of Scalaz for a few years now. I started Scalaz in 2007, when I learned that Scala had these two features (which are extremely important to library design). These features have enabled the encoding of much more advanced concepts — what about those?

Some concepts that belong way higher than Martin’s L3 specification are:

  • encoding type-level transformations
  • advanced purely-functional data structures
  • automated specification-based testing and associated library authoring requirements to effectively achieve it
  • encoding algebraic structures of category theory and ensuring these are available for practical use
  • understanding type theory, its goals and (truly understanding, for real) the benefits and trade-offs of static program verification
  • attempting a high (read: extremely high) degree of abstraction in the context of Scala’s limited laziness abilities.

I take issue here because keen learners may be fooled into believing that as they are confident in understanding all concepts at L3, then they are qualified to be an “expert library designer.” I put it to you that there is an extraordinary leap from L3 to an API designer of any considerable merit. Indeed, in my opinion, L3 is just enough knowledge to even begin practical library design. Before I attract a charge of shooting too high or the usual anti-intellectual nonsense, I like to remind others that I like to aim high, very high. I encourage you to do so too. Nothing more.

I recently gave a beginner API design quiz. I use it in programming classes that I teach, where many people struggle with it. When these students eventually break through, they are equipped with a reasonable fundamental understanding of writing practical libraries and APIs. However, note the triviality of the problem and the observation (if you’ll trust me), that many programmers have difficulty. This leaves open a huge opportunity for improvement in problem-solving skills — let’s take it!

I’d hate to believe that L3 is “expert.” I’d be saddened to think others have been tricked into settling there too. Surely we can shoot higher than that Martin.

Edit

A case in point, I was directed to this comment:

If it [scala] is a failure, why has the language - for exaple [sic] - the best collection library of all languages currently out there?

Honestly and without any intention to exaggerate, it boggles my mind with fascination as to what could cause such a rapid and extreme departure from reality. Working with both Scala and Haskell in depth for many years, there is nothing more disheartening than putting Haskell aside and dealing with the underwhelming practicalities of Scala’s (and therefore, Java’s) libraries. Indeed, this Great Big Hole That Is Still Gaping Wide was one of the primary motivations for the creation of Scalaz when I was working on a commercial application yearning for useful libraries. That was many years ago. Nothing has changed.

That’s just Haskell. There are other examples of programming environments that completely annihilate Scala/Java in terms of useful libraries.

To believe the aforementioned statement is perhaps a symptom of shooting so disastrously low as purported by “L3, the highest level of expertise.” In other words, there are serious and observable consequences for having such low standards, to such an extent that one may even fall under the illusion presented in this statement. I hope you’ll agree that there are practical implications for believing these things.

Then I witnessed this comment, which completely misses the point. Specifically, this commenter is not at what Odersky would call L3, since the comment demonstrates lack of understanding of higher-order polymorphism (aka higher-kinds). I don’t wish to pull apart every naive comment, but I do wish to point out that we can aim much higher than this.

MUCH MUCH HIGHER

I lament, but fight on, for the encouragement of setting a higher standard. Sorry guys, but you’re way off base. We can do a fuck-load better than this and we have done exactly that, elsewhere.

– a former contributor to the Scala collection libraries with high hopes

Java is pass by value

Thursday, January 13th, 2011

I was linked to this silly thread today. I didn’t read much of it and I recommend you don’t either.

Instead, take note, it’s yet another example of Java programmers knowing one language and knowing it poorly. This consistent observation is not particularly interesting, but this particular misunderstanding was cleared up years ago. I went through an old Java FAQ database that I had written while I was working on the IBM implementation in 2000 where I explained all this. It was even asked in one of my wanky Java certifications back then. There were surely other explanations around at the time too. Sigh, Java guys, please… do yourself a favour and at least understand the shitty language that you hold so dear.

Java has two possible parameter types

  1. Object references
  2. primitives (restricted to 8 in total)

Note here that Java never passes objects, ever. They do not appear in the list above, double-check to make sure. Now, you don’t have to take my word for it; after all, I’m just a former implementer of the language and API specification and I assure you, that doesn’t change a thing with regard to credibility. However, just what was I implementing back then? It was a number of specifications; one of which was called The Java Virtual Machine Specification (VMS).

Here is section 2.10.1 of the VMS. I will quote the whole section to make sure this point sinks in. If you are unsure whether Java passes by reference or value or some variation, then please read it again. Repeat this until you comprehend the important part. Here goes:

The formal parameters of a method, if any, are specified by a list of comma-separated parameter specifiers. Each parameter specifier consists of a type and an identifier that specifies the name of the parameter. When the method is invoked, the values of the actual argument expressions initialize newly created parameter variables (§2.5), each of the declared type, before execution of the body of the method.

A method parameter of type float always contains an element of the float value set (§2.4.3); similarly, a method parameter of type double always contains an element of the double value set. It is not permitted for a method parameter of type float to contain an element of the float-extended-exponent value set that is not also an element of the float value set, nor for a method parameter of type double to contain an element of the double-extended-exponent value set that is not also an element of the double value set.

Where an actual argument expression corresponding to a parameter variable is not FP-strict (§2.18), evaluation of that actual argument expression is permitted to use values drawn from the appropriate extended-exponent value sets. Prior to being stored in the parameter variable, the result of such an expression is mapped to the nearest value in the corresponding standard value set by method invocation conversion (§2.6.8).

Let me extract a really important part:

…initialize newly created parameter variables (§2.5), each of the declared type, before execution of the body of the method.

Did you see that? Java is pass by value, without reservation. It says so in the specification. It is even observable by writing a trivial program.

Object o = new Object();

Now I know you may be accustomed to calling ‘o’ an object here, and it may even be the source of confusion, but it’s not an object. It’s an object reference. The object referred to by ‘o’ has no name.

When you pass ‘o’, it is copied, as per the specification, to a new reference, specified by the method being called. This means that if you reassign that reference, it cannot be observed outside of that method. Of course, since it is a copy of the method parameter.

void method(Object o) {
  o = x; // not observable outside local scope
}

If you were to dereference ‘o’ you may be able to execute some effect that may be outside of the method. Note the adjective here, dereference. What are we dereferencing? An object reference of course! Surely you have seen a NullPointerException. Know what this means? You dereferenced a reference which held no object!

I don’t know how else to make this clear, so I won’t continue trying.

Java is pass by value.

Scala exercise with types and abstraction

Sunday, January 9th, 2011

Write an API for playing tic-tac-toe. There should be no side-effects (or variables), at all, for real. The move function will take a game state, a Position and it will return a data type that you write yourself.

The following functions (at least) must be supported:

  1. move (as mentioned)
  2. whoseTurn (returns which player’s turn it is)
  3. whoWon (returns who won or if a draw)
  4. playerAt (returns which player, if any, is at a given position)

Importantly, the following must be true:

  1. It is a compile-time error to call move or whoseTurn on a game that has been completed
  2. It is a compile-time error to call whoWon on a game that has not been completed
  3. The playerAt function must be supported on both complete and in-play games

Good luck and may the types be with you.

Configuration versus Code

Sunday, January 9th, 2011

Sometimes I’ll be working away when a colleague will make some distinction between “that which is configuration” and “that which is code.” In all cases, it turns out that this distinction is premised on a having a very narrow understanding of solving software problems. That can’t be good.

When we write compositional code using techniques such as referential transparency, the distinction between configuration and code completely evaporates. I wish to emphasise this evaporation, so I will restate it: it is not possible to determine which is configuration and which is code, except when using very sloppy problem solving habits, no matter how much we wish to save the thesis. I made this emphasis because I have even seen people accept that the delineation disappears, then in the very next breath say something to the effect as if it were still there. Brains are fascinating machines. I digress.

Let us suppose a Haskell program, though, the language is unimportant to this point. We only need to examine the type signature:

application :: IO ()

If we need some form of “configuration”, such as a possible String value with a “default”, we pass it as such:

application :: Maybe String -> IO ()

Then the body of application will apply the default: fromMaybe "default string". Easy right?

You might have multiple configuration values and not necessarily with the type String. Now of course, since we are using Haskell (and not XML!), we can give our configuration values a type! Here is an example:

data Initialisation = Initialisation {
  ioWait :: Int
, performance :: Speed
, password :: String
}

then your application becomes:

application :: Initialisation -> IO ()

With Haskell you also get record selector syntax with this data structure. This means that setting say, 2 of these values can be done with effort proportional to the size of 2. With languages such as Java, achieving this goal results in a quadratic blow-out, requiring n^2 methods with overloads where n is the number of record fields.

Now, notice how doing this is simply, using a function. Let’s be clear, I am using a function, like any other, a function, code. It is not special and does not deserve any elevated status above other functions. No more useless ceremony here.

A good example of an application, that I use each day, is xmonad, which I “configure” by writing Haskell. OK, now let’s be honest, I just write a program and take advantage of the comprehensive libraries.

In some cases that make the distinction between configuration and code, it’s often that an inappropriate language has been chosen to write code in, such as XML. There is a direct mapping between the XML and whatever programming language they are using. However, the XML will often exhibit properties that programming languages such as Haskell exhibit universally e.g. reordering statements does not affect the observable outcome of the program. In other words, this is just functional programming with XML (yeah, my thoughts exactly).

Any effort that delineates between configuration and code is nothing more than a very reliable indicator of sloppy thinking. Think again.

Nothing returns anything, ever!

Tuesday, December 28th, 2010

I once had the following discussion with someone regarding a Java project:

Him: Once we did a project and we didn’t return anything from a method, ever (i.e. void) It went very well.
Me: So everything was in CPS transform then so that you could simulate it?
Him: No, we didn’t ever return anything ever!
Me: So uh, it was uh, in CPS transform then, since er… you know…
Him: No! Nothing. Return. Nothing. Ever. Void. Always!
Me: Er yeah right uh huh.

This person operates under the illusion that I am in an intellectual battle with him, so I can excuse the somewhat awkward discussion. My efforts to destroy this destructive illusion have been repeated failure to date. That’s a side-story.

It occurred to me later, thanks to Edward Kmett, that perhaps it wasn’t a CPS transform but using exceptions instead! I doubt that was the case :) I’m also reasonably confident this discussion was argumentum ad ignorantiam — my converser doesn’t know what CPS transform means (so it can’t possibly be true!), but that’s cool — let’s not dwell on it. Instead, let’s have a look how you can simulate returning a value without actually returning a value using continuation-passing style (CPS)!

We may conjure up both simple and elaborate examples of functions that actually return a value:

Integer wibble(String s, double d)
Swizzler function1(int i, String s, Swazzle z)

I am going to use the trivial example (top one), but I hope you’ll be able to extrapolate to swizzlier cases.

First, note that Java methods may perform side-effects willy-nilly. Passing in a String and a double are not the only values that the function may access. The function may print to standard output, use variables in any scope, read/write files, the network and so on. This changes things a little (read: a lot) with regard to how we look at a function, so perhaps this is why this technique has apparent (read: apparent) merit.

Suppose a very simple interface:

interface To<A> {
  void to(A a);
}

Quite simply, this function takes a polymorphic (aka generic) value and performs a side-effect, perhaps using this value. It is important to point out that this polymorphic interface may be modelled differently e.g. it may not be polymorphic:

interface Stringer {
  void stringer(String s);
}

This interface is exactly equivalent to To<String> so I’m also trusting that you’ll extrapolate my generic example to other possibilities.

Now, instead of returning a type e.g. Integer in the wibble function, we may return void with an additional To<Integer> argument. We can do this for every single function that would otherwise return a value!

How does that work then? Simple really. We compute the Integer as we normally would in the body of wibble and instead of returning it (we can’t of course), we pass it to the to method of the given To<Integer> instance.

void wibble(String s, double d, To<Integer> t)

And so on it goes, for every method.

Essentially, this results in a function that, instead of returning a value of type T, returns a value of the type (T => void) => void where (T => void) is represented by the To interface and is of course, in the position of a method argument where that method returns void. This is exactly equivalent to a specific example of a continuation. We are doing a CPS transform to simulate returning a value!

To summarise the formula:

For a method that would normally return a type T, we can transform it in such a way to accept an argument of type To<T> and returns void.

As for the merits of doing this, well I’ll leave that for another battle :) Further, there are some interesting properties about continuations, in particular, they are a monad, perhaps even the mother of all monads, but we’ll leave all that for another day too.

Edit: Per comments, I think a clarification is in order. Doing this is a very very bad idea on the JVM (without tail-call elimination — note that the IBM implementation only does direct TCE). Doing this results in a significant performance degradation and increased syntax for zero benefit. I didn’t bring this up because I was never going to get that far in the original conversation that I mention. Beware.

Bye Reddit

Tuesday, December 28th, 2010

With idiotic shit like this, followed by overwhelmingly stupid commentary like this and the most ignorant and intellectually under-equipped programmer on the internet (prove me wrong, but not now, in my moment of lament), I have cancelled my reddit account.

Fool is me for not doing it sooner. Bye.

The Writer Monad using Scala (example)

Sunday, December 12th, 2010

Prompted by a question on the scala mailing list, I have produced below a minimal library representing a data type called Logger and its monad implementation (see the map and flatMap methods).

This data type represents logging in a pure functional environment where you maintain compositionality of your code (i.e. no side-effects) and also, brevity of code — see the example usage below using a for-comprehension demonstrating this.

trait Monoid[A] {
  def append(a1: A, a2: A): A
  def empty: A
}
 
object Monoid {
  implicit def ListMonoid[A]: Monoid[List[A]] = new Monoid[List[A]] {
    def append(a1: List[A], a2: List[A]) = a1 ::: a2
    def empty = Nil
  }
}
 
case class Logger[LOG, A](log: LOG, value: A) {
  def map[B](f: A => B) = 
    Logger(log, f(value))
 
  def flatMap[B](f: A => Logger[LOG, B])(implicit m: Monoid[LOG]) = {
    val x = f(value)
    Logger(m.append(log, x.log), x.value)
  }
 
  // insert much more
}
 
object Logger {
  def unital[LOG, A](value: A)(implicit m: Monoid[LOG]) =
    Logger(m.empty, value)
 
  // insert much more
}
 
object Util {
  // utility
  implicit def ListLogUtil[A](a: A) = new {
    def ~>[B](b: B) = Logger(List(a), b)
 
    def <|~[B](k: A => B) = Logger(List(k(a)), a)
  }
 
  def noLog[A](a: A) =
    Logger.unital[List[String], A](a)
}
 
// begin example
 
/*
$ scala Main 456
RESULT: 7000
 
LOG
---
adding one to 456
converting int to string 457
checking length of 457 for evenness
multiplying 1000 by 7 to produce 7000
*/
object Main {
  import Util._
 
  def main(args: Array[String]) {
    val x = args(0).toInt // parse int from command line
 
    val r = 
      for(a <- addOne(x);
          b <- intString(a);
          c <- lengthIsEven(b);
          d <- noLog(hundredOrThousand(c));
          e <- times7(d)
         ) yield e
 
    println("RESULT: " + r.value)
    println
    println("LOG")
    println("---")
    r.log foreach println
  }
 
  def addOne(n: Int) = 
    ("adding one to " + n) ~> (n + 1)
 
  def intString(n: Int) = 
    ("converting int to string " + n) ~> n.toString
 
  def lengthIsEven(s: String) =
    ("checking length of " + s + " for evenness") ~> (s.length % 2 == 0)
 
  def hundredOrThousand(b: Boolean) = // no logging
    if(b) 100 else 1000
 
  def times7(n: Int) =
    (n * 7) <|~ ("multiplying " + n + " by 7 to produce " + _)
}

Dear Java library guy

Wednesday, November 24th, 2010
import java.io.File;
import java.util.Calendar;
 
import static java.util.Calendar.DAY_OF_WEEK;
import static java.util.Calendar.THURSDAY;
import static java.util.Calendar.TUESDAY;
import static java.util.Calendar.WEDNESDAY;
 
public class ThreeAdder {
  // Convenience method to add the two given numbers, then adds 3.
  // It's really convenient, promise.
  // It even has tests and they passed! See below.
  public static int addThen3(int a, int b) {
    if(new File("/etc/passwd").exists() && a < 100) {
      return a + b + 3;
    } else if (b == 2) {
      int day = Calendar.getInstance().get(DAY_OF_WEEK);
      if (day == TUESDAY || day == WEDNESDAY || day == THURSDAY)
        return 5 + a;
      else
        return 9;
    } else if(a == 0) {
      return b + 3;
    } else if(b == 0) {
      return a + 3;
    } else {
      return 8;
    }
  }
 
  public static <A> String assertEq(String name, A x, A y) {
    return name + (x.equals(y) ?
      " [PASSED]" :
      " [FAILED] {" + x + "}  {" + y + '}');
  }
 
  public static void main(String[] args) {
    String[] out = {
        assertEq("adding to zero", addThen3(0, 0), 3)
    ,   assertEq("adding to zero", addThen3(0, 4), 7)
    ,   assertEq("adding to zero", addThen3(4, 0), 7)
    ,   assertEq("adding to zero", addThen3(1, 0), 4)
    ,   assertEq("adding to zero", addThen3(0, 1), 4)
    ,   assertEq("adding to zero", addThen3(0, 1), 4)
    ,   assertEq("small numbers",  addThen3(2, 4), 9)
    ,   assertEq("small numbers",  addThen3(2, 3), 8)
    ,   assertEq("small numbers",  addThen3(3, 3), 9)
    ,   assertEq("small numbers",  addThen3(3, 2), 8)
    };
 
    for(String o : out) {
      System.out.println(o);
    }
  }
}

No.