Archive for March, 2010

What Does Functional Programming Mean?

Wednesday, March 31st, 2010

Here are some slides to a short talk I gave a few weeks ago.

Hoping to get less ridiculous (i.e. more insightful) blog comments…

Scalaz IRC

Saturday, March 27th, 2010

Scalaz now has an IRC channel.

irc://irc.freenode.net/#scalaz

Monad exercises in Scala

Thursday, March 25th, 2010

A result of discussion in the #scala IRC channel.

A colleague has asked me to convert this to Haskell, which I have done below.

  • The trait Monad answers the question “What does monad mean?”
  • The object Monad answers the question “What are some examples?”
  • The object MonadicFunctions answers the question “What are the practical implications?”

If there are any questions or you get stuck, the #scala or #scalaz channel on Freenode could help out.

// 1. Start here. Observe this trait
trait Monad[M[_]] {
  def flatMap[A, B](a: M[A], f: A => M[B]): M[B]
  def unital[A](a: A): M[A]
}
 
// A simple data type, which turns out to satisfy the above trait
case class Inter[A](f: Int => A)
 
// So does this.
case class Identity[A](a: A)
 
// Monad implementations
object Monad {
  // 2. Replace error("todo") with an implementation
  def ListMonad: Monad[List] = error("todo")
 
  // 3. Replace error("todo") with an implementation
  def OptionMonad: Monad[Option] = error("todo")
 
  // 4. Replace error("todo") with an implementation
  def InterMonad: Monad[Inter] = error("todo")
 
  // 5. Replace error("todo") with an implementation
  def IdentityMonad: Monad[Identity] = error("todo")
}
 
object MonadicFunctions {
  // 6. Replace error("todo") with an implementation
  def sequence[M[_], A](as: List[M[A]], m: Monad[M]): M[List[A]] =
    error("todo")
 
  // 7. Replace error("todo") with an implementation
  def fmap[M[_], A, B](a: M[A], f: A => B, m: Monad[M]): M[B] =
    error("todo")
 
  // 8. Replace error("todo") with an implementation
  def flatten[M[_], A](a: M[M[A]], m: Monad[M]): M[A] =
    error("todo")
 
  // 9. Replace error("todo") with an implementation
  def apply[M[_], A, B](f: M[A => B], a: M[A], m: Monad[M]): M[B] =
    error("todo")
 
  // 10. Replace error("todo") with an implementation
  def filterM[M[_], A](f: A => M[Boolean], as: List[A]
    , m: Monad[M]): M[List[A]] =
    error("todo")
 
  // 11. Replace error("todo") with an implementation
  def replicateM[M[_], A](n: Int, a: M[A], m: Monad[M]): M[List[A]] =
    error("todo: flatMap n times to produce a list")
 
  // 12. Replace error("todo") with an implementation
  def lift2[M[_], A, B, C](f: (A, B) => C, a: M[A], b: M[B]
    , m: Monad[M]): M[C] =
    error("todo")
 
  // lift3, lift4, etc. Interesting question: Can we have liftN?
}

Haskell

  • The data Monad' answers the question “What does monad mean?”
  • The functions under *** Monad implementations *** answers the question “What are some examples?”
  • The functions under *** Monadic Functions *** answers the question “What are the practical implications?”
{-# LANGUAGE RankNTypes #-}
 
-- 1. Start here. Observe this data type
data Monad' m = Monad' {
  unital :: forall a. a -> m a,
  flatMap :: forall a b. m a -> (a -> m b) -> m b
}
 
-- A simple data type, which turns out to satisfy the above trait
newtype Inter a = Inter { f :: Int -> a }
 
-- So does this.
newtype Identity a = Identity { a :: a }
  deriving Show
 
-- *** Monad implementations ***
 
-- 2. Replace error "todo" with an implementation
listMonad :: Monad' []
listMonad = error "todo"
 
-- 3. Replace error "todo" with an implementation
maybeMonad :: Monad' Maybe
maybeMonad = error "todo"
 
-- 4. Replace error "todo" with an implementation
interMonad :: Monad' Inter
interMonad = error "todo"
 
-- 5. Replace error "todo" with an implementation
identityMonad :: Monad' Identity
identityMonad = error "todo"
 
-- *** Monadic functions ***
 
-- 6. Replace error "todo" with an implementation
sequence' :: [m a] -> Monad' m -> m [a]
sequence' = error "todo"
 
-- 7. Replace error "todo" with an implementation
fmap' :: m a -> (a -> b) -> Monad' m -> m b
fmap' = error "todo"
 
-- 8. Replace error "todo" with an implementation
flatten :: m (m a) -> Monad' m -> m a
flatten = error "todo"
 
-- 9. Replace error "todo" with an implementation
apply :: m (a -> b) -> m a -> Monad' m -> m b
apply = error "todo"
 
-- 10. Replace error "todo" with an implementation
filterM' :: (a -> m Bool) -> [a] -> Monad' m -> m [a]
filterM' = error "todo"
 
-- 11. Replace error "todo" with an implementation
replicateM' :: Int -> m a -> Monad' m -> m [a]
replicateM' = error "todo: flatMap n times to produce a list"
 
-- 12. Replace error "todo" with an implementation
lift2 :: (a -> b -> c) -> m a -> m b -> Monad' m -> m c
lift2 = error "todo"
 
-- lift3, lift4, etc. Interesting question: Can we have liftN?

Why are there no big applications written using functional languages?

Wednesday, March 24th, 2010

Because there is no such thing as a big application. There is only bigger or smaller. This is a central tenet of functional programming. “Big application” is a euphemism for “My idea of programming does not scale beyond this point.” You don’t realise how much information you give away when you ask this question.

So can we can stop with the piffle and get on with the interesting and important stuff? Ta.

A poke at the essence of functional programming

Wednesday, March 24th, 2010

I used to work for IBM on the Java implementation. I learned the language inside-out. I did all those Sun certifications and other spanky things. I wanted to understand what a lot of people alleged was so special. I didn’t ever find it.

I have found that few people can tell me the answer to this question. If you don’t know the answer, don’t fret; it’s not the important part.

method(s1.charAt(i), s2.charAt(j));

Assuming s1 and s2 are both of the type java.lang.String, then which call to charAt will occur first?

Many people would correctly guess at the left-most one. This is correct and is mandated by the specification.

However, on introspection, the reason nobody really knows is because it doesn’t matter. If the specification implementation had a bug and executed the right-most call first, then we, the programmer, would never even know. We gloss over this every day when we read Java code.

However, does this hold for all functions? What if it was something other than charAt? No, unfortunately, this only holds true for a specific set of functions. The charAt function is referentially transparent. For any given String and any given int then charAt will consistently return the same char. This is true for other referentially transparent functions too, but not any arbitrary function. Imagine if charAt did a database call or something like that!

Let us suppose now a new language feature that enforced the referential transparency of our functions. If it is referentially transparent, the compiler makes sure of it. Now imagine a new language where every function was referentially transparent.

All of a sudden, in the blink of an imagined hypothetical, the explicit order of invocation is no longer important. Just like that, poof, gone.

Welcome to the beginning of an understanding of the essence of functional programming.

Have fun! :)

I have found that…

Tuesday, March 23rd, 2010

I have found that many classes are created for the specific purpose of a sequence function in the ((->) t) monad, particularly in Java, C# and Python. Create a class, with a constructor that takes an argument (t) so that one may call many of its methods, each of which has access to t.

sequence :: [m a] -> m [a]
sequence* :: [t -> a] -> t -> [a]

If we consider the type of t which we shall call Swizzle and the created class we shall call SwizzleManager then

// A constructor accepting a Swizzle
SwizzleManager m = new SwizzleManager(t);
// One of the following usually follow:
//   A list constructed by the results of executing several methods on 'm'
List<R> = { m.a(x), m.b(y), m.c(z) }
//   A loop over a list of the results of executing several methods on 'm'
for(R r : { m.a(x), m.b(y), m.c(z) }) {
  use(r);
}
//   A list of effects to execute using 'm'
m.a(x);
m.b(y);
m.c(z);

Automated Validation with Applicatives and Semigroups (Part 2 - Java)

Sunday, March 21st, 2010

In a previous post, I mentioned a small library for validating using an applicative functor pattern with a semigroup for accumulating errors using Haskell, Scala and Java programming languages. In this post, I will give a set up for an example usage, but not necessarily a complete example. This is left as an exercise and may be elaborated on in a future post.

I will start with Java. First we must decide how we are going to accumulate errors. I have decided to store them in a LinkedList. In more practical languages with a better collections library, we would probably use something else. We will use something else for Scala and Haskell (later!), or you could use the Functional Java extension. In the meantime, we will use java.util.LinkedList. We start by writing its Semigroup implementation:

public static <A> Semigroup<LinkedList<A>> LinkedListSemigroup() {
  return new Semigroup<LinkedList<A>>() {
    public LinkedList<A> append(final LinkedList<A> a1,
                                final LinkedList<A> a2) {
      final LinkedList<A> r = new LinkedList<A>(a1);
      r.addAll(a2);
      return r;
    }
  };
}

This is very straight-forward. In the previous example, I mentioned a class Person that is made of an age and a name. The age is an integer between 0 and 130 while the name is any string that starts with an upper-case character. Let’s write these data types:

// int wrapper between 0 and 130
class Age {
  private final int i;
  private Age(final int i) { this.i = i; }
  public int value() { return i; }
  public static Age age(final int i) {
    if(i <= 0 || i >= 130)
      throw new Error("out of range");
    else
      return new Age(i);
  }
}

And here is Name:

// String wrapper starts with upper-case
class Name {
  private final String s;
  private Name(final String s) { this.s = s; }
  public String value() { return s; }
  public static Name name(final String s) {
    if(s.isEmpty() || !Character.isUpperCase(s.charAt(0)))
      throw new java.lang.Error();
    else
      return new Name(s);
  }
}

I won’t bother writing the Person data type, but it is sufficient to say it will have an Age field and a Name field.

Now for validation. Suppose we have two string values; one each for age and name. We would like to check these for validation and return either one or more error messages (String) or a Person. More succinctly, we want a function with the type:

String -> String -> Validation<LinkedList<String>, Person>>

How are we going to achieve this function? First we must say how to create an Age from a String or an error message if we cannot:

String -> Validation<LinkedList<String>, Age>>

and same for Name

String -> Validation<LinkedList<String, Name>>

We also need a function to create a Person from an Age and a Name

Age -> Name -> Person

This is simple. It’s the Person constructor.

So to sum up, we need to write a function with this type:

Arguments:

  •   F<String, Validation<LinkedList<String>, Age>>>
  •   F<String, Validation<LinkedList<String>, Name>>>
  •   F<Age, F<Name, Person>>
  •   Semigroup<LinkedList<String>>

Return type:

F<String, F<String, <Validation<LinkedList<String>, Person>>>>

Of course such a function is likely to be polymorphic, rather than specifying concrete types. I recommend starting by writing a function with this type:

Arguments:

  •   F<T, F<U, V>>
  •   F<A, Validation<E, T>>
  •   F<B, Validation<E, U>>

Return type:

F<A, F<B, Validation<E, V>>

This function can be written by using the constructs mentioned in the previous post. I’m out of breath. Java is incredibly laborious.

Scala and Haskell for another time!

Automated Validation with Applicatives and Semigroups (for Sanjiv)

Sunday, March 21st, 2010

Sanjiv is an ex-colleague of mine who recently gave an excellent presentation at Brisbane Functional Programming Group. His presentation was on the use of the disjoint union algebraic data type for representing error handling or “validation”. This data type is often called Either. Sanjiv used the Scala version for his presentation.

Here I am going to write a data type that is just like (isomorphic to) Either called Validation. There will be two constructors for failure and success. I will be using Haskell, Scala and Java. I am going to present a function that is mentioned in an excellent paper called Applicative Programming with Effects.

There is a slight difference in my implementation to the function in this paper. The one mentioned in the paper uses a Monoid constraint, while I am using the more general Semigroup. This allows data types that are semigroups but not monoids (all monoids are semigroups). In particular, a non-empty list is a semigroup but not a monoid.

This constraint on the failing value allows the user to automatically accumulate errors as they chain through the Validation values, for example, by keeping them in a non-empty list. I am not going to give example usages of this code in this post because I think it is a great exercise for others and I do not want to spoil it. It is sufficient to say that any usage that type-checks is likely to be a useful example. I may give examples in the future if there is some confusion that needs clarification.

The function can accumulate Validation values using the applicative programming pattern. If all given are successful, you’ll be left with a function that takes all the successful values to a new value, which will be returned as a success. If at least one is not successful, the applicative pattern will begin accumulating with that error value and any future values.

I recommend starting with a simple example such as a Person type with an age :: Int and name :: String with imposed validation rules such as “age must be above 0 and less than 130″ and “name must start with a capital letter”. The applied function at the end should be ValidatedInt -> ValidatedString -> Person.

Like I said, if there is any confusion, I’ll expand later. Put the questions in the comments. Enjoy! :)

Here is a Haskell implementation of this:

data Validation e a = Fail e | Success a deriving (Eq, Show)
 
-- Associative, binary operation (Monoid without identity)
class Semigroup a where
  append :: a -> a -> a
 
(<+>) :: Validation e a -> (a -> b) -> Validation e b
Fail e <+> _ = Fail e
Success a <+> f = Success (f a)
 
(<*>) :: (Semigroup e) => Validation e a
    -> Validation e (a -> b)
    -> Validation e b
Fail e1 <*> Fail e2 = Fail (e1 `append` e2)
Fail e1 <*> Success _ = Fail e1
Success _ <*> Fail e2 = Fail e2
Success a <*> Success f = Success (f a)

And Scala:

sealed trait Validation[E, A] {
  def <+>[B](f: A => B): Validation[E, B] = this match {
    case Fail(e) => Fail(e)
    case Success(a) => Success(f(a))
  }
 
  def <*>[B](f: Validation[E, A => B])(implicit s: Semigroup[E])
    : Validation[E, B] = this match {
    case Fail(e1) => f match {
      case Fail(e2) => Fail(s append (e1, e2))
      case Success(_) => Fail(e1)
    }
    case Success(a) => f match {
      case Fail(e2) => Fail(e2)
      case Success(f) => Success(f(a))
    }
  }
}
case class Fail[E, A](e: E) extends Validation[E, A]
case class Success[E, A](a: A) extends Validation[E, A]
 
// Associative binary operation (Monoid without identity)
case class Semigroup[A](append: (A, A) => A)

And now, for the allegedly practical Java. Hold your breath:

// Java pre-amble, sigh.
interface F<X, Y> {
  Y apply(X x);
}
 
// Associative binary operation (Monoid without identity)
interface Semigroup<A> {
  A append(A a1, A a2);
}
 
abstract class Validation<E, A> {
  // No algebraic data types in Java. Use a Church encoding (catamorphism).
  public abstract <X> X fold(F<E, X> fail, F<A, X> success);
 
  // Construction for fail
  public static <E, A> Validation<E, A> fail(final E e) {
    return new Validation<E, A>() {
      public <X> X fold(final F<E, X> fail, final F<A, X> success) {
        return fail.apply(e);
      }
    };
  }
 
  // Construction for success
  public static <E, A> Validation<E, A> success(final A a) {
    return new Validation<E, A>() {
      public <X> X fold(final F<E, X> fail, final F<A, X> success) {
        return success.apply(a);
      }
    };
  }
 
  // <+>
  public <B> Validation<E, B> map(final F<A, B> f) {
    return new Validation<E, B>() {
      public <X> X fold(final F<E, X> fail, final F<B, X> success) {
        return Validation.this.fold(fail, new F<A, X>() {
          public X apply(final A a) {
            return success.apply(f.apply(a));
          }
        });
      }
    };
  }
 
  // <*>
  public <B> Validation<E, B> applicativate(
      final Validation<E, F<A, B>> f,
      final Semigroup<E> s /* no implicits or type-classes in Java */) {
    return Validation.this.fold(new F<E, Validation<E, B>>() {
      public Validation<E, B> apply(final E e1) {
        return f.fold(new F<E, Validation<E, B>>() {
          public Validation<E, B> apply(final E e2) {
            // case (Fail(e1), Fail(e2))
            return Validation.fail(s.append(e1, e2)); 
          }
        }, new F<F<A, B>, Validation<E, B>>() {
          public Validation<E, B> apply(final F<A, B> f) {
            // case (Fail(e1), Success(f))
            return Validation.fail(e1); 
          }
        });
      }
    }, new F<A, Validation<E, B>>() {
      public Validation<E, B> apply(final A a) {
        return f.fold(new F<E, Validation<E, B>>() {
          public Validation<E, B> apply(final E e2) {
            // case (Success(a), Fail(e2))
            return Validation.fail(e2); 
          }
        }, new F<F<A, B>, Validation<E, B>>() {
          public Validation<E, B> apply(final F<A, B> f) {
            // case (Success(a), Success(f))
            return Validation.success(f.apply(a)); 
          }
        });
      }
    });
  }
}