(I don't know Erlang, and I can't write Haskell, but I think I can answer nevertheless)
Well, in that interview the example of a random number generation library is given. Here is a possible stateful interface:
# create a new RNG
var rng = RNG(seed)
# every time we call the next(ceil) method, we get a new random number
print rng.next(10)
print rng.next(10)
print rng.next(10)
Output may be 5 2 7
. To someone who likes immutability, this is plain wrong! It should be 5 5 5
, because we called the method on the same object.
So what would a stateless interface be? We can view the sequence of random numbers as a lazily evaluated list, where next
actually retrieves the head:
let rng = RNG(seed)
let n : rng = rng in
print n
let n : rng = rng in
print n
let n : rng in
print n
With such an interface, we can always revert to a previous state. If two pieces of your code refer to the same RNG, they will actually get the same sequence of numbers. In a functional mindset, this is highly desirable.
Implementing this in a stateful language isn't that complicated. For example:
import scala.util.Random
import scala.collection.immutable.LinearSeq
class StatelessRNG (private val statefulRNG: Random, bound: Int) extends LinearSeq[Int] {
private lazy val next = (statefulRNG.nextInt(bound), new StatelessRNG(statefulRNG, bound))
// the rest is just there to satisfy the LinearSeq trait
override def head = next._1
override def tail = next._2
override def isEmpty = false
override def apply(i: Int): Int = throw new UnsupportedOperationException()
override def length = throw new UnsupportedOperationException()
}
// print out three nums
val rng = new StatelessRNG(new Random(), 10)
rng.take(3) foreach (n => println(n))
Once you add a bit of syntactic sugar so that it feels like a list, this is actually quite nice.